Add rule date to validation messages so new rules can be highlighted

This commit is contained in:
Grahame Grieve 2022-11-22 05:58:02 -03:00
parent ed5930b68d
commit 24331956f1
18 changed files with 864 additions and 822 deletions

View File

@ -67,6 +67,7 @@ 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.json.JsonUtilities;
import org.hl7.fhir.utilities.validation.ValidationMessage;
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;
@ -126,7 +127,7 @@ public class JsonParser extends ParserBase {
try { try {
obj = JsonTrackingParser.parse(source, map, false, allowComments); obj = JsonTrackingParser.parse(source, map, false, allowComments);
} catch (Exception e) { } catch (Exception e) {
logError(-1, -1,context.formatMessage(I18nConstants.DOCUMENT), IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_, e.getMessage()), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, -1, -1,context.formatMessage(I18nConstants.DOCUMENT), IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_, e.getMessage()), IssueSeverity.FATAL);
return null; return null;
} }
assert (map.containsKey(obj)); assert (map.containsKey(obj));
@ -156,7 +157,7 @@ public class JsonParser extends ParserBase {
if (sd == null) { if (sd == null) {
JsonElement rt = object.get("resourceType"); JsonElement rt = object.get("resourceType");
if (rt == null) { if (rt == null) {
logError(line(object), col(object), "$", IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, line(object), col(object), "$", IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL);
return null; return null;
} else { } else {
name = rt.getAsString(); name = rt.getAsString();
@ -190,7 +191,7 @@ public class JsonParser extends ParserBase {
// } // }
} }
if (!found) if (!found)
logError(line(object), col(object), path, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(object), col(object), path, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR);
} }
} }
@ -216,7 +217,7 @@ public class JsonParser extends ParserBase {
Property property = new Property(context, sd.getSnapshot().getElementFirstRep(), sd, element.getProperty().getUtils()); Property property = new Property(context, sd.getSnapshot().getElementFirstRep(), sd, element.getProperty().getUtils());
parseChildItem(path, object, element, null, property); parseChildItem(path, object, element, null, property);
} else { } else {
logError(line(e.getValue()), col(e.getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_, e.getKey()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e.getValue()), col(e.getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_, e.getKey()), IssueSeverity.ERROR);
} }
} }
} }
@ -231,12 +232,12 @@ public class JsonParser extends ParserBase {
if (processed != null) processed.add(property.getJsonName()); if (processed != null) processed.add(property.getJsonName());
String type = getTypeFromJsonType(je); 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, describeType(je), property.getName(), property.typeSummary()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, 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, describeType(je), property.getName(), type, property.typeSummary()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, 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 {
@ -291,7 +292,7 @@ public class JsonParser extends ParserBase {
if (property.canBeEmpty()) { if (property.canBeEmpty()) {
// nothing // nothing
} else { } else {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ARRAY_CANNOT_BE_EMPTY), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ARRAY_CANNOT_BE_EMPTY), IssueSeverity.ERROR);
} }
} }
int c = 0; int c = 0;
@ -303,20 +304,20 @@ public class JsonParser extends ParserBase {
String code = property.getJsonKeyProperty(); String code = property.getJsonKeyProperty();
List<Property> properties = property.getChildProperties(element.getName(), null); List<Property> properties = property.getChildProperties(element.getName(), null);
if (properties.size() != 2) { if (properties.size() != 2) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_CHILD_COUNT, propNames(properties)), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_CHILD_COUNT, propNames(properties)), IssueSeverity.ERROR);
} else { } else {
Property propK = properties.get(0); Property propK = properties.get(0);
Property propV = properties.get(1); Property propV = properties.get(1);
if (!propK.getName().equals(code)) { if (!propK.getName().equals(code)) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_NAME, propNames(properties)), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.OBJECT_CANNOT_BE_KEYED_ARRAY_PROP_NAME, propNames(properties)), IssueSeverity.ERROR);
} else if (!propK.isPrimitive()) { } else if (!propK.isPrimitive()) {
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(ValidationMessage.NO_RULE_DATE, 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(ValidationMessage.NO_RULE_DATE, 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() && propV.getName().endsWith("[x]")) { } 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(ValidationMessage.NO_RULE_DATE, 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(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(e)), IssueSeverity.ERROR);
} else { } else {
JsonObject o = (JsonObject) e; JsonObject o = (JsonObject) e;
int i = 0; int i = 0;
@ -342,12 +343,12 @@ public class JsonParser extends ParserBase {
ok = false; ok = false;
String type = getTypeFromJsonType(pv.getValue()); String type = getTypeFromJsonType(pv.getValue());
if (type == null) { if (type == null) {
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(ValidationMessage.NO_RULE_DATE, 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);
} else if (propV.hasType(type)) { } else if (propV.hasType(type)) {
pvl = new Property(propV.getContext(), propV.getDefinition(), propV.getStructure(), propV.getUtils(), type); pvl = new Property(propV.getContext(), propV.getDefinition(), propV.getStructure(), propV.getUtils(), type);
ok = true; ok = true;
} else { } 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); logError(ValidationMessage.NO_RULE_DATE, 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) { if (ok) {
@ -359,7 +360,7 @@ public class JsonParser extends ParserBase {
} else if (pv.getValue() instanceof JsonObject || pv.getValue() instanceof JsonNull) { } else if (pv.getValue() instanceof JsonObject || pv.getValue() instanceof JsonNull) {
parseChildComplexInstance(npathV, fpathV, n, pvl, pvl.getName(), pv.getValue()); parseChildComplexInstance(npathV, fpathV, n, pvl, pvl.getName(), pv.getValue());
} else { } else {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(pv.getValue())), IssueSeverity.ERROR);
} }
} }
i++; i++;
@ -368,7 +369,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_, describe(e), name, path), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, 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);
} }
@ -397,19 +398,19 @@ public class JsonParser extends ParserBase {
if (type != null) { if (type != null) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, type); StructureDefinition sd = context.fetchResource(StructureDefinition.class, type);
if (sd == null) { if (sd == null) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_ILLEGAL_TYPE, type, cond), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_ILLEGAL_TYPE, type, cond), IssueSeverity.ERROR);
} else { } else {
if (sd.getAbstract()) { if (sd.getAbstract()) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_ABSTRACT_TYPE, type, cond), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_ABSTRACT_TYPE, type, cond), IssueSeverity.ERROR);
} }
property = property.cloneToType(sd); property = property.cloneToType(sd);
} }
} else { } else {
StructureDefinition sd = context.fetchTypeDefinition(property.getType()); StructureDefinition sd = context.fetchTypeDefinition(property.getType());
if (sd == null) { if (sd == null) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_NM_ILLEGAL_TYPE, property.getType()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_NM_ILLEGAL_TYPE, property.getType()), IssueSeverity.ERROR);
} else if (sd.getAbstract()) { } else if (sd.getAbstract()) {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_NM_ABSTRACT_TYPE, property.getType()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.TYPE_SPECIFIER_NM_ABSTRACT_TYPE, property.getType()), IssueSeverity.ERROR);
} }
} }
} }
@ -433,7 +434,7 @@ public class JsonParser extends ParserBase {
n.setNull(true); n.setNull(true);
// nothing to do, it's ok, but we treat it like it doesn't exist // nothing to do, it's ok, but we treat it like it doesn't exist
} else { } else {
logError(line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE__NOT_, (property.isList() ? "an Array" : "an Object"), describe(e), name, npath), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE__NOT_, (property.isList() ? "an Array" : "an Object"), describe(e), name, npath), IssueSeverity.ERROR);
} }
} }
@ -487,11 +488,11 @@ public class JsonParser extends ParserBase {
if (property.isList()) { if (property.isList()) {
boolean ok = true; boolean ok = true;
if (!(main == null || main instanceof JsonArray)) { if (!(main == null || main instanceof JsonArray)) {
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main), name, path), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main), name, path), IssueSeverity.ERROR);
ok = false; ok = false;
} }
if (!(fork == null || fork instanceof JsonArray)) { if (!(fork == null || fork instanceof JsonArray)) {
logError(line(fork), col(fork), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_BASE_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main), name, path), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(fork), col(fork), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_BASE_PROPERTY_MUST_BE_AN_ARRAY_NOT_, describe(main), name, path), IssueSeverity.ERROR);
ok = false; ok = false;
} }
if (ok) { if (ok) {
@ -519,10 +520,10 @@ public class JsonParser extends ParserBase {
private void parseChildPrimitiveInstance(Element element, Property property, String name, String npath, String fpath, JsonElement main, JsonElement fork) throws FHIRException { private void parseChildPrimitiveInstance(Element element, Property property, String name, String npath, String fpath, JsonElement main, JsonElement fork) throws FHIRException {
if (main != null && !(main instanceof JsonPrimitive)) if (main != null && !(main instanceof JsonPrimitive))
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage( logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(
I18nConstants.THIS_PROPERTY_MUST_BE_AN_SIMPLE_VALUE_NOT_, describe(main), name, npath), IssueSeverity.ERROR); I18nConstants.THIS_PROPERTY_MUST_BE_AN_SIMPLE_VALUE_NOT_, describe(main), name, npath), IssueSeverity.ERROR);
else if (fork != null && !(fork instanceof JsonObject)) else if (fork != null && !(fork instanceof JsonObject))
logError(line(fork), col(fork), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(fork), name, npath), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(fork), col(fork), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_AN_OBJECT_NOT_, describe(fork), name, npath), IssueSeverity.ERROR);
else { else {
Element n = new Element(name, property).markLocation(line(main != null ? main : fork), col(main != null ? main : fork)); Element n = new Element(name, property).markLocation(line(main != null ? main : fork), col(main != null ? main : fork));
n.setPath(fpath); n.setPath(fpath);
@ -541,24 +542,24 @@ public class JsonParser extends ParserBase {
n.setXhtml(xhtml.setXmlMode(true).parse(n.getValue(), null).getDocumentElement()); n.setXhtml(xhtml.setXmlMode(true).parse(n.getValue(), null).getDocumentElement());
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
for (StringPair s : xhtml.getValidationIssues()) { for (StringPair s : xhtml.getValidationIssues()) {
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(s.getName(), s.getValue()), IssueSeverity.ERROR); logError("2022-11-17", line(main), col(main), npath, IssueType.INVALID, context.formatMessage(s.getName(), s.getValue()), IssueSeverity.ERROR);
} }
} }
} catch (Exception e) { } catch (Exception e) {
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_XHTML_, e.getMessage()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_XHTML_, e.getMessage()), IssueSeverity.ERROR);
} }
} }
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
// now we cross-check the primitive format against the stated type // now we cross-check the primitive format against the stated type
if (Utilities.existsInList(n.getType(), "boolean")) { if (Utilities.existsInList(n.getType(), "boolean")) {
if (!p.isBoolean()) { if (!p.isBoolean()) {
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_BOOLEAN), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_BOOLEAN), IssueSeverity.ERROR);
} }
} else if (Utilities.existsInList(n.getType(), "integer", "unsignedInt", "positiveInt", "decimal")) { } else if (Utilities.existsInList(n.getType(), "integer", "unsignedInt", "positiveInt", "decimal")) {
if (!p.isNumber()) if (!p.isNumber())
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_NUMBER), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_NUMBER), IssueSeverity.ERROR);
} else if (!p.isString()) } else if (!p.isString())
logError(line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_STRING), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(main), col(main), npath, IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_JSON_THE_PRIMITIVE_VALUE_MUST_BE_A_STRING), IssueSeverity.ERROR);
} }
} }
if (fork != null) { if (fork != null) {
@ -573,12 +574,12 @@ public class JsonParser extends ParserBase {
private void parseResource(String npath, JsonObject res, Element parent, Property elementProperty) throws FHIRException { private void parseResource(String npath, JsonObject res, Element parent, Property elementProperty) throws FHIRException {
JsonElement rt = res.get("resourceType"); JsonElement rt = res.get("resourceType");
if (rt == null) { if (rt == null) {
logError(line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNABLE_TO_FIND_RESOURCETYPE_PROPERTY), IssueSeverity.FATAL);
} else { } else {
String name = rt.getAsString(); String name = rt.getAsString();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null)); StructureDefinition sd = context.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(name, null));
if (sd == null) { if (sd == null) {
logError(line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, line(res), col(res), npath, IssueType.INVALID, context.formatMessage(I18nConstants.CONTAINED_RESOURCE_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL);
} else { } else {
parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities), SpecialElement.fromProperty(parent.getProperty()), elementProperty); parent.updateProperty(new Property(context, sd.getSnapshot().getElement().get(0), sd, this.profileUtilities), SpecialElement.fromProperty(parent.getProperty()), elementProperty);
parent.setType(name); parent.setType(name);

View File

@ -138,10 +138,11 @@ public abstract class ParserBase {
public abstract void compose(Element e, OutputStream destination, OutputStyle style, String base) throws FHIRException, IOException; public abstract void compose(Element e, OutputStream destination, OutputStyle style, String base) throws FHIRException, IOException;
//FIXME: i18n should be done here //FIXME: i18n should be done here
public void logError(int line, int col, String path, IssueType type, String message, IssueSeverity level) throws FHIRFormatError { public void logError(String ruleDate, int line, int col, String path, IssueType type, String message, IssueSeverity level) throws FHIRFormatError {
if (errors != null) { if (errors != null) {
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
ValidationMessage msg = new ValidationMessage(Source.InstanceValidator, type, line, col, path, message, level); ValidationMessage msg = new ValidationMessage(Source.InstanceValidator, type, line, col, path, message, level);
msg.setRuleDate(ruleDate);
errors.add(msg); errors.add(msg);
} else if (level == IssueSeverity.FATAL || (level == IssueSeverity.ERROR && policy == ValidationPolicy.QUICK)) } else if (level == IssueSeverity.FATAL || (level == IssueSeverity.ERROR && policy == ValidationPolicy.QUICK))
throw new FHIRFormatError(message+String.format(" at line %d col %d", line, col)); throw new FHIRFormatError(message+String.format(" at line %d col %d", line, col));
@ -151,11 +152,11 @@ public abstract class ParserBase {
protected StructureDefinition getDefinition(int line, int col, String ns, String name) throws FHIRFormatError { protected StructureDefinition getDefinition(int line, int col, String ns, String name) throws FHIRFormatError {
if (ns == null) { if (ns == null) {
logError(line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS__CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAMESPACE, name), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS__CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAMESPACE, name), IssueSeverity.FATAL);
return null; return null;
} }
if (name == null) { if (name == null) {
logError(line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAME), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAME), IssueSeverity.FATAL);
return null; return null;
} }
for (StructureDefinition sd : new ContextUtilities(context).allStructures()) { for (StructureDefinition sd : new ContextUtilities(context).allStructures()) {
@ -167,13 +168,13 @@ public abstract class ParserBase {
return sd; return sd;
} }
} }
logError(line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAMESPACENAME_, ns, name), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAMESPACENAME_, ns, name), IssueSeverity.FATAL);
return null; return null;
} }
protected StructureDefinition getDefinition(int line, int col, String name) throws FHIRFormatError { protected StructureDefinition getDefinition(int line, int col, String name) throws FHIRFormatError {
if (name == null) { if (name == null) {
logError(line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAME), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_CANNOT_BE_PARSED_AS_A_FHIR_OBJECT_NO_NAME), IssueSeverity.FATAL);
return null; return null;
} }
// first pass: only look at base definitions // first pass: only look at base definitions
@ -189,7 +190,7 @@ public abstract class ParserBase {
return sd; return sd;
} }
} }
logError(line, col, name, IssueType.STRUCTURE, context.formatMessage(I18nConstants.THIS_DOES_NOT_APPEAR_TO_BE_A_FHIR_RESOURCE_UNKNOWN_NAME_, name), IssueSeverity.FATAL); logError(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; return null;
} }

View File

@ -24,6 +24,7 @@ import org.hl7.fhir.utilities.VersionUtilities;
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.json.JsonUtilities;
import org.hl7.fhir.utilities.validation.ValidationMessage;
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;
@ -71,7 +72,7 @@ public class SHCParser extends ParserBase {
int i = 0; int i = 0;
for (JsonElement e : arr) { for (JsonElement e : arr) {
if (!(e instanceof JsonPrimitive)) { if (!(e instanceof JsonPrimitive)) {
logError(line(e), col(e), "$.verifiableCredential["+i+"]", IssueType.STRUCTURE, "Wrong Property verifiableCredential in JSON Payload. Expected : String but found "+JsonUtilities.type(e), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), "$.verifiableCredential["+i+"]", IssueType.STRUCTURE, "Wrong Property verifiableCredential in JSON Payload. Expected : String but found "+JsonUtilities.type(e), IssueSeverity.ERROR);
} else { } else {
list.add(e.getAsString()); list.add(e.getAsString());
} }
@ -91,19 +92,19 @@ public class SHCParser extends ParserBase {
try { try {
jwt = decodeJWT(ssrc); jwt = decodeJWT(ssrc);
} catch (Exception e) { } catch (Exception e) {
logError(1, 1, prefix+"JWT", IssueType.INVALID, "Unable to decode JWT token", IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, 1, 1, prefix+"JWT", IssueType.INVALID, "Unable to decode JWT token", IssueSeverity.ERROR);
return res; return res;
} }
map = jwt.map; map = jwt.map;
checkNamedProperties(jwt.getPayload(), prefix+"payload", "iss", "nbf", "vc"); checkNamedProperties(jwt.getPayload(), prefix+"payload", "iss", "nbf", "vc");
checkProperty(jwt.getPayload(), prefix+"payload", "iss", true, "String"); checkProperty(jwt.getPayload(), prefix+"payload", "iss", true, "String");
logError(1, 1, prefix+"JWT", IssueType.INFORMATIONAL, "The FHIR Validator does not check the JWT signature "+ logError(ValidationMessage.NO_RULE_DATE, 1, 1, prefix+"JWT", IssueType.INFORMATIONAL, "The FHIR Validator does not check the JWT signature "+
"(see https://demo-portals.smarthealth.cards/VerifierPortal.html or https://github.com/smart-on-fhir/health-cards-dev-tools) (Issuer = '"+jwt.getPayload().get("iss").getAsString()+"')", IssueSeverity.INFORMATION); "(see https://demo-portals.smarthealth.cards/VerifierPortal.html or https://github.com/smart-on-fhir/health-cards-dev-tools) (Issuer = '"+jwt.getPayload().get("iss").getAsString()+"')", IssueSeverity.INFORMATION);
checkProperty(jwt.getPayload(), prefix+"payload", "nbf", true, "Number"); checkProperty(jwt.getPayload(), prefix+"payload", "nbf", true, "Number");
JsonObject vc = jwt.getPayload().getAsJsonObject("vc"); JsonObject vc = jwt.getPayload().getAsJsonObject("vc");
if (vc == null) { if (vc == null) {
logError(1, 1, "JWT", IssueType.STRUCTURE, "Unable to find property 'vc' in the payload", IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, 1, 1, "JWT", IssueType.STRUCTURE, "Unable to find property 'vc' in the payload", IssueSeverity.ERROR);
return res; return res;
} }
String path = prefix+"payload.vc"; String path = prefix+"payload.vc";
@ -115,14 +116,14 @@ public class SHCParser extends ParserBase {
int i = 0; int i = 0;
for (JsonElement e : type) { for (JsonElement e : type) {
if (!(e instanceof JsonPrimitive)) { if (!(e instanceof JsonPrimitive)) {
logError(line(e), col(e), path+".type["+i+"]", IssueType.STRUCTURE, "Wrong Property Type in JSON Payload. Expected : String but found "+JsonUtilities.type(e), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), path+".type["+i+"]", IssueType.STRUCTURE, "Wrong Property Type in JSON Payload. Expected : String but found "+JsonUtilities.type(e), IssueSeverity.ERROR);
} else { } else {
types.add(e.getAsString()); types.add(e.getAsString());
} }
i++; i++;
} }
if (!types.contains("https://smarthealth.cards#health-card")) { if (!types.contains("https://smarthealth.cards#health-card")) {
logError(line(vc), col(vc), path, IssueType.STRUCTURE, "Card does not claim to be of type https://smarthealth.cards#health-card, cannot validate", IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(vc), col(vc), path, IssueType.STRUCTURE, "Card does not claim to be of type https://smarthealth.cards#health-card, cannot validate", IssueSeverity.ERROR);
return res; return res;
} }
if (!checkProperty(vc, path, "credentialSubject", true, "Object")) { if (!checkProperty(vc, path, "credentialSubject", true, "Object")) {
@ -135,7 +136,7 @@ public class SHCParser extends ParserBase {
} }
JsonElement fv = cs.get("fhirVersion"); JsonElement fv = cs.get("fhirVersion");
if (!VersionUtilities.versionsCompatible(context.getVersion(), fv.getAsString())) { if (!VersionUtilities.versionsCompatible(context.getVersion(), fv.getAsString())) {
logError(line(fv), col(fv), path+".fhirVersion", IssueType.STRUCTURE, "Card claims to be of version "+fv.getAsString()+", cannot be validated against version "+context.getVersion(), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(fv), col(fv), path+".fhirVersion", IssueType.STRUCTURE, "Card claims to be of version "+fv.getAsString()+", cannot be validated against version "+context.getVersion(), IssueSeverity.ERROR);
return res; return res;
} }
if (!checkProperty(cs, path, "fhirBundle", true, "Object")) { if (!checkProperty(cs, path, "fhirBundle", true, "Object")) {
@ -171,12 +172,12 @@ public class SHCParser extends ParserBase {
if (e != null) { if (e != null) {
String t = JsonUtilities.type(e); String t = JsonUtilities.type(e);
if (!type.equals(t)) { if (!type.equals(t)) {
logError(line(e), col(e), path+"."+name, IssueType.STRUCTURE, "Wrong Property Type in JSON Payload. Expected : "+type+" but found "+t, IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(e), col(e), path+"."+name, IssueType.STRUCTURE, "Wrong Property Type in JSON Payload. Expected : "+type+" but found "+t, IssueSeverity.ERROR);
} else { } else {
return true; return true;
} }
} else if (required) { } else if (required) {
logError(line(obj), col(obj), path, IssueType.STRUCTURE, "Missing Property in JSON Payload: "+name, IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(obj), col(obj), path, IssueType.STRUCTURE, "Missing Property in JSON Payload: "+name, IssueSeverity.ERROR);
} else { } else {
return true; return true;
} }
@ -186,7 +187,7 @@ public class SHCParser extends ParserBase {
private void checkNamedProperties(JsonObject obj, String path, String... names) { private void checkNamedProperties(JsonObject obj, String path, String... names) {
for (Entry<String, JsonElement> e : obj.entrySet()) { for (Entry<String, JsonElement> e : obj.entrySet()) {
if (!Utilities.existsInList(e.getKey(), names)) { if (!Utilities.existsInList(e.getKey(), names)) {
logError(line(e.getValue()), col(e.getValue()), path+"."+e.getKey(), IssueType.STRUCTURE, "Unknown Property in JSON Payload", IssueSeverity.WARNING); logError(ValidationMessage.NO_RULE_DATE, line(e.getValue()), col(e.getValue()), path+"."+e.getKey(), IssueType.STRUCTURE, "Unknown Property in JSON Payload", IssueSeverity.WARNING);
} }
} }
} }
@ -257,7 +258,7 @@ public class SHCParser extends ParserBase {
jwt = decodeQRCode(jwt); jwt = decodeQRCode(jwt);
} }
if (jwt.length() > MAX_ALLOWED_SHC_LENGTH) { if (jwt.length() > MAX_ALLOWED_SHC_LENGTH) {
logError(-1, -1, "jwt", IssueType.TOOLONG, "JWT Payload limit length is "+MAX_ALLOWED_SHC_LENGTH+" bytes for a single image - this has "+jwt.length()+" bytes", IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, -1, -1, "jwt", IssueType.TOOLONG, "JWT Payload limit length is "+MAX_ALLOWED_SHC_LENGTH+" bytes for a single image - this has "+jwt.length()+" bytes", IssueSeverity.ERROR);
} }
String[] parts = splitToken(jwt); String[] parts = splitToken(jwt);

View File

@ -60,6 +60,7 @@ import org.hl7.fhir.utilities.turtle.Turtle.TTLList;
import org.hl7.fhir.utilities.turtle.Turtle.TTLLiteral; import org.hl7.fhir.utilities.turtle.Turtle.TTLLiteral;
import org.hl7.fhir.utilities.turtle.Turtle.TTLObject; import org.hl7.fhir.utilities.turtle.Turtle.TTLObject;
import org.hl7.fhir.utilities.turtle.Turtle.TTLURL; import org.hl7.fhir.utilities.turtle.Turtle.TTLURL;
import org.hl7.fhir.utilities.validation.ValidationMessage;
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;
@ -82,7 +83,7 @@ public class TurtleParser extends ParserBase {
try { try {
src.parse(TextFile.streamToString(input)); src.parse(TextFile.streamToString(input));
} catch (Exception e) { } catch (Exception e) {
logError(-1, -1, "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_TURTLE_, e.getMessage()), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, -1, -1, "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.ERROR_PARSING_TURTLE_, e.getMessage()), IssueSeverity.FATAL);
return null; return null;
} }
Element e = parse(src); Element e = parse(src);
@ -111,7 +112,7 @@ public class TurtleParser extends ParserBase {
// still here: well, we didn't find a start point // still here: well, we didn't find a start point
String msg = "Error parsing Turtle: unable to find any node maked as the entry point (where " + FHIR_URI_BASE + "nodeRole = " + FHIR_URI_BASE + "treeRoot)"; String msg = "Error parsing Turtle: unable to find any node maked as the entry point (where " + FHIR_URI_BASE + "nodeRole = " + FHIR_URI_BASE + "treeRoot)";
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
logError(-1, -1, "(document)", IssueType.INVALID, msg, IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, -1, -1, "(document)", IssueType.INVALID, msg, IssueSeverity.FATAL);
return null; return null;
} else { } else {
throw new FHIRFormatError(msg); throw new FHIRFormatError(msg);
@ -121,7 +122,7 @@ public class TurtleParser extends ParserBase {
private Element parse(Turtle src, TTLComplex cmp) throws FHIRException { private Element parse(Turtle src, TTLComplex cmp) throws FHIRException {
TTLObject type = cmp.getPredicates().get("http://www.w3.org/2000/01/rdf-schema#type"); TTLObject type = cmp.getPredicates().get("http://www.w3.org/2000/01/rdf-schema#type");
if (type == null) { if (type == null) {
logError(cmp.getLine(), cmp.getCol(), "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.UNKNOWN_RESOURCE_TYPE_MISSING_RDFSTYPE), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, cmp.getLine(), cmp.getCol(), "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.UNKNOWN_RESOURCE_TYPE_MISSING_RDFSTYPE), IssueSeverity.FATAL);
return null; return null;
} }
if (type instanceof TTLList) { if (type instanceof TTLList) {
@ -134,7 +135,7 @@ public class TurtleParser extends ParserBase {
} }
} }
if (!(type instanceof TTLURL)) { if (!(type instanceof TTLURL)) {
logError(cmp.getLine(), cmp.getCol(), "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.UNEXPECTED_DATATYPE_FOR_RDFSTYPE), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, cmp.getLine(), cmp.getCol(), "(document)", IssueType.INVALID, context.formatMessage(I18nConstants.UNEXPECTED_DATATYPE_FOR_RDFSTYPE), IssueSeverity.FATAL);
return null; return null;
} }
String name = ((TTLURL) type).getUri(); String name = ((TTLURL) type).getUri();
@ -179,7 +180,7 @@ public class TurtleParser extends ParserBase {
for (String u : object.getPredicates().keySet()) { for (String u : object.getPredicates().keySet()) {
if (!processed.contains(u)) { if (!processed.contains(u)) {
TTLObject n = object.getPredicates().get(u); TTLObject n = object.getPredicates().get(u);
logError(n.getLine(), n.getCol(), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PREDICATE_, u), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, n.getLine(), n.getCol(), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PREDICATE_, u), IssueSeverity.ERROR);
} }
} }
} }
@ -218,13 +219,13 @@ public class TurtleParser extends ParserBase {
// todo: check type // todo: check type
n.setValue(value); n.setValue(value);
} else } else
logError(object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_A_LITERAL_NOT_, "a "+e.getClass().getName()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_A_LITERAL_NOT_, "a "+e.getClass().getName()), IssueSeverity.ERROR);
} }
} else } else
parseChildren(src, npath, child, n, false); parseChildren(src, npath, child, n, false);
} else } else
logError(object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_A_URI_OR_BNODE_NOT_, "a "+e.getClass().getName()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.THIS_PROPERTY_MUST_BE_A_URI_OR_BNODE_NOT_, "a "+e.getClass().getName()), IssueSeverity.ERROR);
} }
@ -240,7 +241,7 @@ public class TurtleParser extends ParserBase {
String url = ((TTLURL) e).getUri(); String url = ((TTLURL) e).getUri();
obj = src.getObject(url); obj = src.getObject(url);
if (obj == null) { if (obj == null) {
logError(e.getLine(), e.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.REFERENCE_TO__CANNOT_BE_RESOLVED, url), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, e.getLine(), e.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.REFERENCE_TO__CANNOT_BE_RESOLVED, url), IssueSeverity.FATAL);
return; return;
} }
} else } else
@ -248,7 +249,7 @@ public class TurtleParser extends ParserBase {
TTLObject type = obj.getPredicates().get("http://www.w3.org/2000/01/rdf-schema#type"); TTLObject type = obj.getPredicates().get("http://www.w3.org/2000/01/rdf-schema#type");
if (type == null) { if (type == null) {
logError(object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNKNOWN_RESOURCE_TYPE_MISSING_RDFSTYPE), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNKNOWN_RESOURCE_TYPE_MISSING_RDFSTYPE), IssueSeverity.FATAL);
return; return;
} }
if (type instanceof TTLList) { if (type instanceof TTLList) {
@ -261,7 +262,7 @@ public class TurtleParser extends ParserBase {
} }
} }
if (!(type instanceof TTLURL)) { if (!(type instanceof TTLURL)) {
logError(object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNEXPECTED_DATATYPE_FOR_RDFSTYPE), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, object.getLine(), object.getCol(), npath, IssueType.INVALID, context.formatMessage(I18nConstants.UNEXPECTED_DATATYPE_FOR_RDFSTYPE), IssueSeverity.FATAL);
return; return;
} }
String rt = ((TTLURL) type).getUri(); String rt = ((TTLURL) type).getUri();

View File

@ -67,6 +67,7 @@ import org.hl7.fhir.utilities.ElementDecoration;
import org.hl7.fhir.utilities.StringPair; import org.hl7.fhir.utilities.StringPair;
import org.hl7.fhir.utilities.Utilities; 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.validation.ValidationMessage;
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.CDANarrativeFormat; import org.hl7.fhir.utilities.xhtml.CDANarrativeFormat;
@ -160,9 +161,9 @@ public class XmlParser extends ParserBase {
if (e.getMessage().contains("lineNumber:") && e.getMessage().contains("columnNumber:")) { if (e.getMessage().contains("lineNumber:") && e.getMessage().contains("columnNumber:")) {
int line = Utilities.parseInt(extractVal(e.getMessage(), "lineNumber"), 0); int line = Utilities.parseInt(extractVal(e.getMessage(), "lineNumber"), 0);
int col = Utilities.parseInt(extractVal(e.getMessage(), "columnNumber"), 0); int col = Utilities.parseInt(extractVal(e.getMessage(), "columnNumber"), 0);
logError(line, col, "(xml)", IssueType.INVALID, e.getMessage().substring(e.getMessage().lastIndexOf(";")+1).trim(), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, line, col, "(xml)", IssueType.INVALID, e.getMessage().substring(e.getMessage().lastIndexOf(";")+1).trim(), IssueSeverity.FATAL);
} else { } else {
logError(0, 0, "(xml)", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL); logError(ValidationMessage.NO_RULE_DATE, 0, 0, "(xml)", IssueType.INVALID, e.getMessage(), IssueSeverity.FATAL);
} }
doc = null; doc = null;
} }
@ -186,7 +187,7 @@ public class XmlParser extends ParserBase {
Node node = document.getFirstChild(); Node node = document.getFirstChild();
while (node != null) { while (node != null) {
if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE)
logError(line(document, false), col(document, false), "(document)", IssueType.INVALID, context.formatMessage( logError(ValidationMessage.NO_RULE_DATE, line(document, false), col(document, false), "(document)", IssueType.INVALID, context.formatMessage(
I18nConstants.NO_PROCESSING_INSTRUCTIONS_ALLOWED_IN_RESOURCES), IssueSeverity.ERROR); I18nConstants.NO_PROCESSING_INSTRUCTIONS_ALLOWED_IN_RESOURCES), IssueSeverity.ERROR);
node = node.getNextSibling(); node = node.getNextSibling();
} }
@ -266,14 +267,14 @@ public class XmlParser extends ParserBase {
private void checkElement(org.w3c.dom.Element element, String path, Property prop) throws FHIRFormatError { private void checkElement(org.w3c.dom.Element element, String path, Property prop) throws FHIRFormatError {
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
if (empty(element) && FormatUtilities.FHIR_NS.equals(element.getNamespaceURI())) // this rule only applies to FHIR Content if (empty(element) && FormatUtilities.FHIR_NS.equals(element.getNamespaceURI())) // this rule only applies to FHIR Content
logError(line(element, false), col(element, false), path, IssueType.INVALID, context.formatMessage(I18nConstants.ELEMENT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(element, false), col(element, false), path, IssueType.INVALID, context.formatMessage(I18nConstants.ELEMENT_MUST_HAVE_SOME_CONTENT), IssueSeverity.ERROR);
String ns = prop.getXmlNamespace(); String ns = prop.getXmlNamespace();
String elementNs = element.getNamespaceURI(); String elementNs = element.getNamespaceURI();
if (elementNs == null) { if (elementNs == null) {
elementNs = "noNamespace"; elementNs = "noNamespace";
} }
if (!elementNs.equals(ns)) if (!elementNs.equals(ns))
logError(line(element, false), col(element, false), path, IssueType.INVALID, context.formatMessage(I18nConstants.WRONG_NAMESPACE__EXPECTED_, ns), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(element, false), col(element, false), path, IssueType.INVALID, context.formatMessage(I18nConstants.WRONG_NAMESPACE__EXPECTED_, ns), IssueSeverity.ERROR);
} }
} }
@ -332,7 +333,7 @@ public class XmlParser extends ParserBase {
} }
line = line(nt, end); line = line(nt, end);
col = col(nt, end); col = col(nt, end);
logError(line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.TEXT_SHOULD_NOT_BE_PRESENT, Utilities.makeSingleLine(n.getTextContent().trim())), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.TEXT_SHOULD_NOT_BE_PRESENT, Utilities.makeSingleLine(n.getTextContent().trim())), IssueSeverity.ERROR);
} }
n = n.getNextSibling(); n = n.getNextSibling();
} }
@ -343,7 +344,7 @@ public class XmlParser extends ParserBase {
Node attr = node.getAttributes().item(i); Node attr = node.getAttributes().item(i);
String value = attr.getNodeValue(); String value = attr.getNodeValue();
if (!validAttrValue(value)) { if (!validAttrValue(value)) {
logError(line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.XML_ATTR_VALUE_INVALID, attr.getNodeName()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line, col, path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.XML_ATTR_VALUE_INVALID, attr.getNodeName()), IssueSeverity.ERROR);
} }
if (!(attr.getNodeName().equals("xmlns") || attr.getNodeName().startsWith("xmlns:"))) { if (!(attr.getNodeName().equals("xmlns") || attr.getNodeName().startsWith("xmlns:"))) {
Property property = getAttrProp(properties, attr.getLocalName(), attr.getNamespaceURI()); Property property = getAttrProp(properties, attr.getLocalName(), attr.getNamespaceURI());
@ -368,7 +369,7 @@ public class XmlParser extends ParserBase {
ok = ok || (attr.getLocalName().equals("schemaLocation")); // xsi:schemalocation allowed for non FHIR content ok = ok || (attr.getLocalName().equals("schemaLocation")); // xsi:schemalocation allowed for non FHIR content
ok = ok || (hasTypeAttr(element) && attr.getLocalName().equals("type") && FormatUtilities.NS_XSI.equals(attr.getNamespaceURI())); // xsi:type allowed if element says so ok = ok || (hasTypeAttr(element) && attr.getLocalName().equals("type") && FormatUtilities.NS_XSI.equals(attr.getNamespaceURI())); // xsi:type allowed if element says so
if (!ok) { if (!ok) {
logError(line(node, false), col(node, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ATTRIBUTE__ON__FOR_TYPE__PROPERTIES__, attr.getNodeName(), node.getNodeName(), element.fhirType(), properties), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(node, false), col(node, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ATTRIBUTE__ON__FOR_TYPE__PROPERTIES__, attr.getNodeName(), node.getNodeName(), element.fhirType(), properties), IssueSeverity.ERROR);
} }
} }
} }
@ -396,7 +397,7 @@ public class XmlParser extends ParserBase {
xhtml = xp.parseHtmlNode((org.w3c.dom.Element) child); xhtml = xp.parseHtmlNode((org.w3c.dom.Element) child);
if (policy == ValidationPolicy.EVERYTHING) { if (policy == ValidationPolicy.EVERYTHING) {
for (StringPair s : xp.getValidationIssues()) { for (StringPair s : xp.getValidationIssues()) {
logError(line(child, false), col(child, false), path, IssueType.INVALID, context.formatMessage(s.getName(), s.getValue()), IssueSeverity.ERROR); logError("2022-11-17", line(child, false), col(child, false), path, IssueType.INVALID, context.formatMessage(s.getName(), s.getValue()), IssueSeverity.ERROR);
} }
} }
} }
@ -421,7 +422,7 @@ public class XmlParser extends ParserBase {
xsiType = ToolingExtensions.readStringExtension(property.getDefinition(), "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype"); xsiType = ToolingExtensions.readStringExtension(property.getDefinition(), "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaulttype");
n.setType(xsiType); n.setType(xsiType);
} else { } else {
logError(line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NO_TYPE_FOUND_ON_, child.getLocalName()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NO_TYPE_FOUND_ON_, child.getLocalName()), IssueSeverity.ERROR);
ok = false; ok = false;
} }
} else { } else {
@ -442,11 +443,11 @@ public class XmlParser extends ParserBase {
} }
} }
} else } else
logError(line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ELEMENT_, child.getLocalName()), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNDEFINED_ELEMENT_, child.getLocalName()), IssueSeverity.ERROR);
} else if (child.getNodeType() == Node.CDATA_SECTION_NODE){ } else if (child.getNodeType() == Node.CDATA_SECTION_NODE){
logError(line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.CDATA_IS_NOT_ALLOWED), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.CDATA_IS_NOT_ALLOWED), IssueSeverity.ERROR);
} else if (!Utilities.existsInList(child.getNodeType(), 3, 8)) { } else if (!Utilities.existsInList(child.getNodeType(), 3, 8)) {
logError(line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NODE_TYPE__IS_NOT_ALLOWED, Integer.toString(child.getNodeType())), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, line(child, false), col(child, false), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.NODE_TYPE__IS_NOT_ALLOWED, Integer.toString(child.getNodeType())), IssueSeverity.ERROR);
} }
child = child.getNextSibling(); child = child.getNextSibling();
} }
@ -801,7 +802,7 @@ public class XmlParser extends ParserBase {
} }
} }
if (e != null && !"UTF-8".equalsIgnoreCase(e)) { if (e != null && !"UTF-8".equalsIgnoreCase(e)) {
logError(0, 0, "XML", IssueType.INVALID, context.formatMessage(I18nConstants.XML_ENCODING_INVALID), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, 0, 0, "XML", IssueType.INVALID, context.formatMessage(I18nConstants.XML_ENCODING_INVALID), IssueSeverity.ERROR);
} }
i = header.indexOf("version=\""); i = header.indexOf("version=\"");
@ -816,7 +817,7 @@ public class XmlParser extends ParserBase {
return "?xml-p1?"; return "?xml-p1?";
} catch (Exception e) { } catch (Exception e) {
// suppress this error // suppress this error
logError(0, 0, "XML", IssueType.INVALID, e.getMessage(), IssueSeverity.ERROR); logError(ValidationMessage.NO_RULE_DATE, 0, 0, "XML", IssueType.INVALID, e.getMessage(), IssueSeverity.ERROR);
} }
return "?xml-p2?"; return "?xml-p2?";
} }

View File

@ -6,6 +6,6 @@ public class CommonPackages {
public static final String VER_XVER = "0.0.11"; public static final String VER_XVER = "0.0.11";
public static final String ID_PUBPACK = "hl7.fhir.pubpack"; public static final String ID_PUBPACK = "hl7.fhir.pubpack";
public static final String VER_PUBPACK = "0.1.3"; public static final String VER_PUBPACK = "0.1.4";
} }

View File

@ -1,5 +1,8 @@
package org.hl7.fhir.utilities.validation; package org.hl7.fhir.utilities.validation;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/* /*
Copyright (c) 2011+, HL7, Inc. Copyright (c) 2011+, HL7, Inc.
All rights reserved. All rights reserved.
@ -61,6 +64,7 @@ package org.hl7.fhir.utilities.validation;
*/ */
import java.util.Comparator; import java.util.Comparator;
import java.util.Date;
import java.util.EnumMap; import java.util.EnumMap;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
@ -516,6 +520,8 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
private boolean slicingHint; private boolean slicingHint;
private boolean signpost; private boolean signpost;
private boolean criticalSignpost; private boolean criticalSignpost;
private Date ruleDate;
public static final String NO_RULE_DATE = null;
/** /**
@ -807,5 +813,26 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
return this; return this;
} }
public Date getRuleDate() {
return ruleDate;
}
public void setRuleDate(Date ruleDate) {
this.ruleDate = ruleDate;
}
public void setRuleDate(String value) {
if (value == null) {
ruleDate = null;
} else {
Date d = null;
try {
d = new SimpleDateFormat("yyyy-MM-dd").parse(value);
} catch (ParseException e) {
e.printStackTrace();
}
ruleDate = d;
}
}
} }

View File

@ -5,7 +5,10 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -127,6 +130,8 @@ public class BaseValidator implements IValidationContextResourceLoader {
} }
} }
public static final String NO_RULE_DATE = ValidationMessage.NO_RULE_DATE;
protected final String META = "meta"; protected final String META = "meta";
protected final String ENTRY = "entry"; protected final String ENTRY = "entry";
protected final String LINK = "link"; protected final String LINK = "link";
@ -209,17 +214,17 @@ public class BaseValidator implements IValidationContextResourceLoader {
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
@Deprecated @Deprecated
protected boolean fail(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg) { protected boolean fail(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.FATAL, null); addValidationMessage(errors, ruleDate, type, line, col, path, msg, IssueSeverity.FATAL, null);
} }
return thePass; return thePass;
} }
protected boolean fail(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean fail(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
String msg = context.formatMessage(theMessage, theMessageArguments); String msg = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.FATAL, theMessage); addValidationMessage(errors, ruleDate, type, line, col, path, msg, IssueSeverity.FATAL, theMessage);
} }
return thePass; return thePass;
} }
@ -232,10 +237,10 @@ public class BaseValidator implements IValidationContextResourceLoader {
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
@Deprecated @Deprecated
protected boolean fail(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String msg) { protected boolean fail(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String msg) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
String path = toPath(pathParts); String path = toPath(pathParts);
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.FATAL, null); addValidationMessage(errors, ruleDate, type, -1, -1, path, msg, IssueSeverity.FATAL, null);
} }
return thePass; return thePass;
} }
@ -248,10 +253,10 @@ public class BaseValidator implements IValidationContextResourceLoader {
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
@Deprecated @Deprecated
protected boolean fail(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean fail(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
String path = toPath(pathParts); String path = toPath(pathParts);
addValidationMessage(errors, type, -1, -1, path, context.formatMessage(theMessage, theMessageArguments), IssueSeverity.FATAL, theMessage); addValidationMessage(errors, ruleDate, type, -1, -1, path, context.formatMessage(theMessage, theMessageArguments), IssueSeverity.FATAL, theMessage);
} }
return thePass; return thePass;
} }
@ -264,9 +269,9 @@ public class BaseValidator implements IValidationContextResourceLoader {
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
@Deprecated @Deprecated
protected boolean fail(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) { protected boolean fail(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.FATAL, null); addValidationMessage(errors, ruleDate, type, -1, -1, path, msg, IssueSeverity.FATAL, null);
} }
return thePass; return thePass;
} }
@ -282,10 +287,10 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean hint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg) { protected boolean hint(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg) {
if (!thePass && doingHints()) { if (!thePass && doingHints()) {
String message = context.formatMessage(msg); String message = context.formatMessage(msg);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, msg); addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, msg);
} }
return thePass; return thePass;
} }
@ -298,9 +303,9 @@ public class BaseValidator implements IValidationContextResourceLoader {
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
//FIXME: formatMessage should be done here //FIXME: formatMessage should be done here
protected boolean slicingHint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, boolean isCritical, String msg, String html, String[] text) { protected boolean slicingHint(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, boolean isCritical, String msg, String html, String[] text) {
if (!thePass && doingHints()) { if (!thePass && doingHints()) {
addValidationMessage(errors, type, line, col, path, msg, IssueSeverity.INFORMATION, null).setSlicingHint(true).setSliceHtml(html, text).setCriticalSignpost(isCritical); addValidationMessage(errors, ruleDate, type, line, col, path, msg, IssueSeverity.INFORMATION, null).setSlicingHint(true).setSliceHtml(html, text).setCriticalSignpost(isCritical);
} }
return thePass; return thePass;
} }
@ -312,31 +317,31 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean hint(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean hint(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingHints()) { if (!thePass && doingHints()) {
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage); addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage);
} }
return thePass; return thePass;
} }
protected boolean hintPlural(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, int num, String theMessage, Object... theMessageArguments) { protected boolean hintPlural(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, int num, String theMessage, Object... theMessageArguments) {
if (!thePass && doingHints()) { if (!thePass && doingHints()) {
String message = context.formatMessagePlural(num, theMessage, theMessageArguments); String message = context.formatMessagePlural(num, theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage); addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage);
} }
return thePass; return thePass;
} }
protected ValidationMessage signpost(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String theMessage, Object... theMessageArguments) { protected ValidationMessage signpost(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, String theMessage, Object... theMessageArguments) {
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
return addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage).setSignpost(true); return addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage).setSignpost(true);
} }
protected boolean txHint(List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean txHint(List<ValidationMessage> errors, String ruleDate, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingHints()) { if (!thePass && doingHints()) {
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.INFORMATION, Source.TerminologyEngine, theMessage).setTxLink(txLink); addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, Source.TerminologyEngine, theMessage).setTxLink(txLink);
} }
return thePass; return thePass;
} }
@ -348,11 +353,11 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean hint(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean hint(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingHints()) { if (!thePass && doingHints()) {
String path = toPath(pathParts); String path = toPath(pathParts);
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.INFORMATION, theMessage); addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.INFORMATION, theMessage);
} }
return thePass; return thePass;
} }
@ -364,10 +369,10 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean hint(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean hint(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingHints()) { if (!thePass && doingHints()) {
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.INFORMATION, null); addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.INFORMATION, null);
} }
return thePass; return thePass;
} }
@ -379,26 +384,27 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean rule(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean rule(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.ERROR, theMessage); addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.ERROR, theMessage);
} }
return thePass; return thePass;
} }
protected boolean rulePlural(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, int num, String theMessage, Object... theMessageArguments) { protected boolean rulePlural(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, int num, String theMessage, Object... theMessageArguments) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
String message = context.formatMessagePlural(num, theMessage, theMessageArguments); String message = context.formatMessagePlural(num, theMessage, theMessageArguments);
addValidationMessage(errors, type, line, col, path, message, IssueSeverity.ERROR, theMessage); addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.ERROR, theMessage);
} }
return thePass; return thePass;
} }
protected boolean txRule(List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean txRule(List<ValidationMessage> errors, String ruleDate, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
ValidationMessage vm = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, message, IssueSeverity.ERROR).setMessageId(theMessage); ValidationMessage vm = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, message, IssueSeverity.ERROR).setMessageId(theMessage);
vm.setRuleDate(ruleDate);
if (checkMsgId(theMessage, vm)) { if (checkMsgId(theMessage, vm)) {
errors.add(vm.setTxLink(txLink)); errors.add(vm.setTxLink(txLink));
} }
@ -413,10 +419,10 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean rule(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String msg) { protected boolean rule(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String msg) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
String path = toPath(pathParts); String path = toPath(pathParts);
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.ERROR, null); addValidationMessage(errors, ruleDate, type, -1, -1, path, msg, IssueSeverity.ERROR, null);
} }
return thePass; return thePass;
} }
@ -428,11 +434,11 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean rule(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean rule(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
String path = toPath(pathParts); String path = toPath(pathParts);
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage); addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage);
} }
return thePass; return thePass;
} }
@ -446,25 +452,25 @@ public class BaseValidator implements IValidationContextResourceLoader {
*/ */
protected boolean rule(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean rule(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage); addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage);
} }
return thePass; return thePass;
} }
protected boolean rulePlural(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, int num, String theMessage, Object... theMessageArguments) { protected boolean rulePlural(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, int num, String theMessage, Object... theMessageArguments) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
String message = context.formatMessagePlural(num, theMessage, theMessageArguments); String message = context.formatMessagePlural(num, theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage); addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage);
} }
return thePass; return thePass;
} }
public boolean rule(List<ValidationMessage> errors, Source source, IssueType type, String path, boolean thePass, String msg) { public boolean rule(List<ValidationMessage> errors, String ruleDate, Source source, IssueType type, String path, boolean thePass, String msg) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.ERROR, source, null); addValidationMessage(errors, ruleDate, type, -1, -1, path, msg, IssueSeverity.ERROR, source, null);
} }
return thePass; return thePass;
} }
@ -476,11 +482,11 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean ruleHtml(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html) { protected boolean ruleHtml(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg, String html) {
if (!thePass && doingErrors()) { if (!thePass && doingErrors()) {
msg = context.formatMessage(msg, null); msg = context.formatMessage(msg, null);
html = context.formatMessage(html, null); html = context.formatMessage(html, null);
addValidationMessage(errors, type, path, msg, html, IssueSeverity.ERROR, null); addValidationMessage(errors, ruleDate, type, path, msg, html, IssueSeverity.ERROR, null);
} }
return thePass; return thePass;
} }
@ -520,33 +526,34 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean warning(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) { protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
String nmsg = context.formatMessage(msg, theMessageArguments); String nmsg = context.formatMessage(msg, theMessageArguments);
IssueSeverity severity = IssueSeverity.WARNING; IssueSeverity severity = IssueSeverity.WARNING;
addValidationMessage(errors, type, line, col, path, nmsg, severity, msg); addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, severity, msg);
} }
return thePass; return thePass;
} }
protected boolean warningPlural(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, int num, String msg, Object... theMessageArguments) { protected boolean warningPlural(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, int num, String msg, Object... theMessageArguments) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
String nmsg = context.formatMessagePlural(num, msg, theMessageArguments); String nmsg = context.formatMessagePlural(num, msg, theMessageArguments);
IssueSeverity severity = IssueSeverity.WARNING; IssueSeverity severity = IssueSeverity.WARNING;
addValidationMessage(errors, type, line, col, path, nmsg, severity, msg); addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, severity, msg);
} }
return thePass; return thePass;
} }
protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, String id) { protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, String id) {
Source source = this.source; Source source = this.source;
return addValidationMessage(errors, type, line, col, path, msg, theSeverity, source, id); return addValidationMessage(errors, ruleDate, type, line, col, path, msg, theSeverity, source, id);
} }
protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, Source theSource, String id) { protected ValidationMessage addValidationMessage(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, String msg, IssueSeverity theSeverity, Source theSource, String id) {
ValidationMessage validationMessage = new ValidationMessage(theSource, type, line, col, path, msg, theSeverity).setMessageId(id); ValidationMessage validationMessage = new ValidationMessage(theSource, type, line, col, path, msg, theSeverity).setMessageId(id);
validationMessage.setRuleDate(ruleDate);
if (doingLevel(theSeverity) && checkMsgId(id, validationMessage)) { if (doingLevel(theSeverity) && checkMsgId(id, validationMessage)) {
errors.add(validationMessage); errors.add(validationMessage);
} }
@ -571,10 +578,11 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean txWarning(List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) { protected boolean txWarning(List<ValidationMessage> errors, String ruleDate, String txLink, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
String nmsg = context.formatMessage(msg, theMessageArguments); String nmsg = context.formatMessage(msg, theMessageArguments);
ValidationMessage vmsg = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(msg); ValidationMessage vmsg = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(msg);
vmsg.setRuleDate(ruleDate);
if (checkMsgId(msg, vmsg)) { if (checkMsgId(msg, vmsg)) {
errors.add(vmsg); errors.add(vmsg);
} }
@ -590,10 +598,11 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean txWarningForLaterRemoval(Object location, List<ValidationMessage> errors, String txLink, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) { protected boolean txWarningForLaterRemoval(Object location, List<ValidationMessage> errors, String ruleDate, String txLink, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
String nmsg = context.formatMessage(msg, theMessageArguments); String nmsg = context.formatMessage(msg, theMessageArguments);
ValidationMessage vmsg = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(msg); ValidationMessage vmsg = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(msg);
vmsg.setRuleDate(ruleDate);
if (checkMsgId(msg, vmsg)) { if (checkMsgId(msg, vmsg)) {
errors.add(vmsg); errors.add(vmsg);
} }
@ -614,12 +623,12 @@ public class BaseValidator implements IValidationContextResourceLoader {
trackedMessages.removeAll(messages); trackedMessages.removeAll(messages);
} }
protected boolean warningOrError(boolean isError, List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) { protected boolean warningOrError(boolean isError, List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass) { if (!thePass) {
String nmsg = context.formatMessage(msg, theMessageArguments); String nmsg = context.formatMessage(msg, theMessageArguments);
IssueSeverity lvl = isError ? IssueSeverity.ERROR : IssueSeverity.WARNING; IssueSeverity lvl = isError ? IssueSeverity.ERROR : IssueSeverity.WARNING;
if (doingLevel(lvl)) { if (doingLevel(lvl)) {
addValidationMessage(errors, type, line, col, path, nmsg, lvl, msg); addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, lvl, msg);
} }
} }
return thePass; return thePass;
@ -633,11 +642,11 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean warning(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
String path = toPath(pathParts); String path = toPath(pathParts);
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.WARNING, theMessage); addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.WARNING, theMessage);
} }
return thePass; return thePass;
} }
@ -649,10 +658,10 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean warning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, Object... theMessageArguments) { protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
String message = context.formatMessage(msg, theMessageArguments); String message = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.WARNING, null); addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.WARNING, null);
} }
return thePass; return thePass;
} }
@ -664,12 +673,12 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean warningOrHint(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, boolean warning, String msg, Object... theMessageArguments) { protected boolean warningOrHint(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, boolean warning, String msg, Object... theMessageArguments) {
if (!thePass) { if (!thePass) {
String message = context.formatMessage(msg, theMessageArguments); String message = context.formatMessage(msg, theMessageArguments);
IssueSeverity lvl = warning ? IssueSeverity.WARNING : IssueSeverity.INFORMATION; IssueSeverity lvl = warning ? IssueSeverity.WARNING : IssueSeverity.INFORMATION;
if (doingLevel(lvl)) { if (doingLevel(lvl)) {
addValidationMessage(errors, type, -1, -1, path, message, lvl, null); addValidationMessage(errors, ruleDate, type, -1, -1, path, message, lvl, null);
} }
} }
return thePass; return thePass;
@ -682,9 +691,9 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean warningHtml(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html) { protected boolean warningHtml(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg, String html) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
addValidationMessage(errors, type, path, msg, html, IssueSeverity.WARNING, null); addValidationMessage(errors, ruleDate, type, path, msg, html, IssueSeverity.WARNING, null);
} }
return thePass; return thePass;
} }
@ -696,10 +705,10 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean warningHtml(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) { protected boolean warningHtml(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
String nmsg = context.formatMessage(msg, theMessageArguments); String nmsg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, path, nmsg, html, IssueSeverity.WARNING, msg); addValidationMessage(errors, ruleDate, type, path, nmsg, html, IssueSeverity.WARNING, msg);
} }
return thePass; return thePass;
} }
@ -712,10 +721,10 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) { protected boolean suppressedwarning(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
String nmsg = context.formatMessage(msg, theMessageArguments); String nmsg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, line, col, path, nmsg, IssueSeverity.INFORMATION, msg); addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, IssueSeverity.INFORMATION, msg);
} }
return thePass; return thePass;
@ -728,11 +737,11 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) { protected boolean suppressedwarning(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
String path = toPath(pathParts); String path = toPath(pathParts);
String message = context.formatMessage(theMessage, theMessageArguments); String message = context.formatMessage(theMessage, theMessageArguments);
addValidationMessage(errors, type, -1, -1, path, message, IssueSeverity.INFORMATION, theMessage); addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.INFORMATION, theMessage);
} }
return thePass; return thePass;
} }
@ -744,9 +753,9 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg) { protected boolean suppressedwarning(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
addValidationMessage(errors, type, -1, -1, path, msg, IssueSeverity.INFORMATION, null); addValidationMessage(errors, ruleDate, type, -1, -1, path, msg, IssueSeverity.INFORMATION, null);
} }
return thePass; return thePass;
} }
@ -758,16 +767,17 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html) { protected boolean suppressedwarning(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg, String html) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
IssueSeverity severity = IssueSeverity.INFORMATION; IssueSeverity severity = IssueSeverity.INFORMATION;
addValidationMessage(errors, type, path, msg, html, severity, null); addValidationMessage(errors, ruleDate, type, path, msg, html, severity, null);
} }
return thePass; return thePass;
} }
protected void addValidationMessage(List<ValidationMessage> errors, IssueType type, String path, String msg, String html, IssueSeverity theSeverity, String id) { protected void addValidationMessage(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, String msg, String html, IssueSeverity theSeverity, String id) {
ValidationMessage vm = new ValidationMessage(source, type, -1, -1, path, msg, html, theSeverity); ValidationMessage vm = new ValidationMessage(source, type, -1, -1, path, msg, html, theSeverity);
vm.setRuleDate(ruleDate);
if (checkMsgId(id, vm)) { if (checkMsgId(id, vm)) {
if (doingLevel(theSeverity)) { if (doingLevel(theSeverity)) {
errors.add(vm.setMessageId(id)); errors.add(vm.setMessageId(id));
@ -782,10 +792,10 @@ public class BaseValidator implements IValidationContextResourceLoader {
* Set this parameter to <code>false</code> if the validation does not pass * Set this parameter to <code>false</code> if the validation does not pass
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation) * @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
*/ */
protected boolean suppressedwarning(List<ValidationMessage> errors, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) { protected boolean suppressedwarning(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) {
if (!thePass && doingWarnings()) { if (!thePass && doingWarnings()) {
String nmsg = context.formatMessage(msg, theMessageArguments); String nmsg = context.formatMessage(msg, theMessageArguments);
addValidationMessage(errors, type, path, nmsg, html, IssueSeverity.INFORMATION, msg); addValidationMessage(errors, ruleDate, type, path, nmsg, html, IssueSeverity.INFORMATION, msg);
} }
return thePass; return thePass;
} }
@ -945,14 +955,14 @@ public class BaseValidator implements IValidationContextResourceLoader {
} else if (fullUrl == null) { } else if (fullUrl == null) {
//This isn't a problem for signatures - if it's a signature, we won't have a resolution for a relative reference. For anything else, this is an error //This isn't a problem for signatures - if it's a signature, we won't have a resolution for a relative reference. For anything else, this is an error
// but this rule doesn't apply for batches or transactions // but this rule doesn't apply for batches or transactions
rule(errors, IssueType.REQUIRED, -1, -1, path, Utilities.existsInList(type, "batch-response", "transaction-response") || path.startsWith("Bundle.signature"), I18nConstants.BUNDLE_BUNDLE_FULLURL_MISSING); rule(errors, NO_RULE_DATE, IssueType.REQUIRED, -1, -1, path, Utilities.existsInList(type, "batch-response", "transaction-response") || path.startsWith("Bundle.signature"), I18nConstants.BUNDLE_BUNDLE_FULLURL_MISSING);
return null; return null;
} else if (ref.split("/").length != 2 && ref.split("/").length != 4) { } else if (ref.split("/").length != 2 && ref.split("/").length != 4) {
if (isTransaction) { if (isTransaction) {
rule(errors, IssueType.INVALID, -1, -1, path, isSearchUrl(ref), I18nConstants.REFERENCE_REF_FORMAT1, ref); rule(errors, NO_RULE_DATE, IssueType.INVALID, -1, -1, path, isSearchUrl(ref), I18nConstants.REFERENCE_REF_FORMAT1, ref);
} else { } else {
rule(errors, IssueType.INVALID, -1, -1, path, false, I18nConstants.REFERENCE_REF_FORMAT2, ref); rule(errors, NO_RULE_DATE, IssueType.INVALID, -1, -1, path, false, I18nConstants.REFERENCE_REF_FORMAT2, ref);
} }
return null; return null;
@ -995,18 +1005,18 @@ public class BaseValidator implements IValidationContextResourceLoader {
if (targetUrl.equals(we.getChildValue(FULL_URL))) { if (targetUrl.equals(we.getChildValue(FULL_URL))) {
Element r = we.getNamedChild(RESOURCE); Element r = we.getNamedChild(RESOURCE);
if (version.isEmpty()) { if (version.isEmpty()) {
rule(errors, IssueType.FORBIDDEN, -1, -1, path, match == null, I18nConstants.BUNDLE_BUNDLE_MULTIPLEMATCHES, ref); rule(errors, NO_RULE_DATE, IssueType.FORBIDDEN, -1, -1, path, match == null, I18nConstants.BUNDLE_BUNDLE_MULTIPLEMATCHES, ref);
match = r; match = r;
matchIndex = i; matchIndex = i;
} else { } else {
try { try {
if (version.equals(r.getChildren(META).get(0).getChildValue("versionId"))) { if (version.equals(r.getChildren(META).get(0).getChildValue("versionId"))) {
rule(errors, IssueType.FORBIDDEN, -1, -1, path, match == null, I18nConstants.BUNDLE_BUNDLE_MULTIPLEMATCHES, ref); rule(errors, NO_RULE_DATE, IssueType.FORBIDDEN, -1, -1, path, match == null, I18nConstants.BUNDLE_BUNDLE_MULTIPLEMATCHES, ref);
match = r; match = r;
matchIndex = i; matchIndex = i;
} }
} catch (Exception e) { } catch (Exception e) {
warning(errors, IssueType.REQUIRED, -1, -1, path, r.getChildren(META).size() == 1 && r.getChildren(META).get(0).getChildValue("versionId") != null, I18nConstants.BUNDLE_BUNDLE_FULLURL_NEEDVERSION, targetUrl); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, -1, -1, path, r.getChildren(META).size() == 1 && r.getChildren(META).get(0).getChildValue("versionId") != null, I18nConstants.BUNDLE_BUNDLE_FULLURL_NEEDVERSION, targetUrl);
// If one of these things is null // If one of these things is null
} }
} }
@ -1014,9 +1024,9 @@ public class BaseValidator implements IValidationContextResourceLoader {
} }
if (match != null && resourceType != null) if (match != null && resourceType != null)
rule(errors, IssueType.REQUIRED, -1, -1, path, match.getType().equals(resourceType), I18nConstants.REFERENCE_REF_RESOURCETYPE, ref, match.getType()); rule(errors, NO_RULE_DATE, IssueType.REQUIRED, -1, -1, path, match.getType().equals(resourceType), I18nConstants.REFERENCE_REF_RESOURCETYPE, ref, match.getType());
if (match == null) { if (match == null) {
warning(errors, IssueType.REQUIRED, -1, -1, path, !ref.startsWith("urn"), I18nConstants.BUNDLE_BUNDLE_NOT_LOCAL, ref); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, -1, -1, path, !ref.startsWith("urn"), I18nConstants.BUNDLE_BUNDLE_NOT_LOCAL, ref);
if (!Utilities.isAbsoluteUrl(ref)) { if (!Utilities.isAbsoluteUrl(ref)) {
String[] p = ref.split("\\/"); String[] p = ref.split("\\/");
List<Element> ml = new ArrayList<>(); List<Element> ml = new ArrayList<>();
@ -1030,15 +1040,15 @@ public class BaseValidator implements IValidationContextResourceLoader {
} }
} }
if (ml.size() > 1) { if (ml.size() > 1) {
warning(errors, IssueType.REQUIRED, -1, -1, path, false, I18nConstants.BUNDLE_POSSSIBLE_MATCHES, ref, targetUrl); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, -1, -1, path, false, I18nConstants.BUNDLE_POSSSIBLE_MATCHES, ref, targetUrl);
} }
for (Element e : ml) { for (Element e : ml) {
String fu = e.getChildValue(FULL_URL); String fu = e.getChildValue(FULL_URL);
int i = entries.indexOf(e); int i = entries.indexOf(e);
if (fu == null) { if (fu == null) {
warning(errors, IssueType.REQUIRED, -1, -1, path, false, I18nConstants.BUNDLE_BUNDLE_POSSIBLE_MATCH_NO_FU, i, ref, targetUrl); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, -1, -1, path, false, I18nConstants.BUNDLE_BUNDLE_POSSIBLE_MATCH_NO_FU, i, ref, targetUrl);
} else { } else {
warning(errors, IssueType.REQUIRED, -1, -1, path, false, I18nConstants.BUNDLE_BUNDLE_POSSIBLE_MATCH_WRONG_FU, i, ref, fu, targetUrl); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, -1, -1, path, false, I18nConstants.BUNDLE_BUNDLE_POSSIBLE_MATCH_WRONG_FU, i, ref, fu, targetUrl);
} }
} }
} }
@ -1087,13 +1097,13 @@ public class BaseValidator implements IValidationContextResourceLoader {
if (isXverUrl(url)) { if (isXverUrl(url)) {
switch (xverStatus(url)) { switch (xverStatus(url)) {
case BadVersion: case BadVersion:
rule(errors, IssueType.BUSINESSRULE, profile.getId(), false, I18nConstants.EXTENSION_EXT_VERSION_INVALID, url, xverVersion(url)); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getId(), false, I18nConstants.EXTENSION_EXT_VERSION_INVALID, url, xverVersion(url));
return null; return null;
case Unknown: case Unknown:
rule(errors, IssueType.BUSINESSRULE, profile.getId(), false, I18nConstants.EXTENSION_EXT_VERSION_INVALIDID, url, xverElementId(url)); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getId(), false, I18nConstants.EXTENSION_EXT_VERSION_INVALIDID, url, xverElementId(url));
return null; return null;
case Invalid: case Invalid:
rule(errors, IssueType.BUSINESSRULE, profile.getId(), false, I18nConstants.EXTENSION_EXT_VERSION_NOCHANGE, url, xverElementId(url)); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getId(), false, I18nConstants.EXTENSION_EXT_VERSION_NOCHANGE, url, xverElementId(url));
return null; return null;
case Valid: case Valid:
StructureDefinition defn = xverDefn(url); StructureDefinition defn = xverDefn(url);
@ -1101,7 +1111,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
context.cacheResource(defn); context.cacheResource(defn);
return defn; return defn;
default: default:
rule(errors, IssueType.INVALID, profile.getId(), false, I18nConstants.EXTENSION_EXT_VERSION_INTERNAL, url); rule(errors, NO_RULE_DATE, IssueType.INVALID, profile.getId(), false, I18nConstants.EXTENSION_EXT_VERSION_INTERNAL, url);
return null; return null;
} }
} else { } else {
@ -1113,13 +1123,13 @@ public class BaseValidator implements IValidationContextResourceLoader {
if (isXverUrl(url)) { if (isXverUrl(url)) {
switch (xverStatus(url)) { switch (xverStatus(url)) {
case BadVersion: case BadVersion:
rule(errors, IssueType.INVALID, element.line(), element.col(), path + "[url='" + url + "']", false, I18nConstants.EXTENSION_EXT_VERSION_INVALID, url, xverVersion(url)); rule(errors, NO_RULE_DATE, IssueType.INVALID, element.line(), element.col(), path + "[url='" + url + "']", false, I18nConstants.EXTENSION_EXT_VERSION_INVALID, url, xverVersion(url));
break; break;
case Unknown: case Unknown:
rule(errors, IssueType.INVALID, element.line(), element.col(), path + "[url='" + url + "']", false, I18nConstants.EXTENSION_EXT_VERSION_INVALIDID, url, xverElementId(url)); rule(errors, NO_RULE_DATE, IssueType.INVALID, element.line(), element.col(), path + "[url='" + url + "']", false, I18nConstants.EXTENSION_EXT_VERSION_INVALIDID, url, xverElementId(url));
break; break;
case Invalid: case Invalid:
rule(errors, IssueType.INVALID, element.line(), element.col(), path + "[url='" + url + "']", false, I18nConstants.EXTENSION_EXT_VERSION_NOCHANGE, url, xverElementId(url)); rule(errors, NO_RULE_DATE, IssueType.INVALID, element.line(), element.col(), path + "[url='" + url + "']", false, I18nConstants.EXTENSION_EXT_VERSION_NOCHANGE, url, xverElementId(url));
break; break;
case Valid: case Valid:
StructureDefinition ex = xverDefn(url); StructureDefinition ex = xverDefn(url);
@ -1127,7 +1137,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
context.cacheResource(ex); context.cacheResource(ex);
return ex; return ex;
default: default:
rule(errors, IssueType.INVALID, element.line(), element.col(), path + "[url='" + url + "']", false, I18nConstants.EXTENSION_EXT_VERSION_INTERNAL, url); rule(errors, NO_RULE_DATE, IssueType.INVALID, element.line(), element.col(), path + "[url='" + url + "']", false, I18nConstants.EXTENSION_EXT_VERSION_INTERNAL, url);
break; break;
} }
} }
@ -1173,7 +1183,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
Resource r5 = null; Resource r5 = null;
switch (v) { switch (v) {
case DSTU1: case DSTU1:
rule(errors, IssueType.INVALID, resource.line(), resource.col(), path, false, I18nConstants.UNSUPPORTED_VERSION_R1, resource.getIdBase()); rule(errors, NO_RULE_DATE, IssueType.INVALID, resource.line(), resource.col(), path, false, I18nConstants.UNSUPPORTED_VERSION_R1, resource.getIdBase());
return null; // this can't happen return null; // this can't happen
case DSTU2: case DSTU2:
org.hl7.fhir.dstu2.model.Resource r2 = new org.hl7.fhir.dstu2.formats.JsonParser().parse(json); org.hl7.fhir.dstu2.model.Resource r2 = new org.hl7.fhir.dstu2.formats.JsonParser().parse(json);
@ -1200,7 +1210,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
if (class1.isInstance(r5)) if (class1.isInstance(r5))
return (Resource) r5; return (Resource) r5;
else { else {
rule(errors, IssueType.INVALID, resource.line(), resource.col(), path, false, I18nConstants.REFERENCE_REF_WRONGTARGET_LOAD, resource.getIdBase(), class1.toString(), r5.fhirType()); rule(errors, NO_RULE_DATE, IssueType.INVALID, resource.line(), resource.col(), path, false, I18nConstants.REFERENCE_REF_WRONGTARGET_LOAD, resource.getIdBase(), class1.toString(), r5.fhirType());
return null; return null;
} }

View File

@ -66,7 +66,7 @@ public class CodeSystemValidator extends BaseValidator {
private void checkCodes(Set<String> codes, List<ConceptDefinitionComponent> list, String path, List<ValidationMessage> errors) { private void checkCodes(Set<String> codes, List<ConceptDefinitionComponent> list, String path, List<ValidationMessage> errors) {
for (ConceptDefinitionComponent cc : list) { for (ConceptDefinitionComponent cc : list) {
String npath = path+".concept.descendents().where(code = '"+cc.getCode()+"')"; String npath = path+".concept.descendents().where(code = '"+cc.getCode()+"')";
rule(errors, IssueType.BUSINESSRULE, npath, !codes.contains(cc.getCode()), "Duplicate Code "+cc.getCode()); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, npath, !codes.contains(cc.getCode()), "Duplicate Code "+cc.getCode());
codes.add(cc.getCode()); codes.add(cc.getCode());
checkCodes(codes, cc.getConcept(), npath, errors); checkCodes(codes, cc.getConcept(), npath, errors);
} }

View File

@ -50,7 +50,7 @@ public class BundleValidator extends BaseValidator {
type = StringUtils.defaultString(type); type = StringUtils.defaultString(type);
if (entries.size() == 0) { if (entries.size() == 0) {
ok = rule(errors, IssueType.INVALID, stack.getLiteralPath(), !(type.equals(DOCUMENT) || type.equals(MESSAGE)), I18nConstants.BUNDLE_BUNDLE_ENTRY_NOFIRST) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, stack.getLiteralPath(), !(type.equals(DOCUMENT) || type.equals(MESSAGE)), I18nConstants.BUNDLE_BUNDLE_ENTRY_NOFIRST) && ok;
} else { } else {
// Get the first entry, the MessageHeader // Get the first entry, the MessageHeader
Element firstEntry = entries.get(0); Element firstEntry = entries.get(0);
@ -61,7 +61,7 @@ public class BundleValidator extends BaseValidator {
if (type.equals(DOCUMENT)) { if (type.equals(DOCUMENT)) {
Element resource = firstEntry.getNamedChild(RESOURCE); Element resource = firstEntry.getNamedChild(RESOURCE);
if (rule(errors, IssueType.INVALID, firstEntry.line(), firstEntry.col(), stack.addToLiteralPath(ENTRY, PATH_ARG), resource != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOFIRSTRESOURCE)) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, firstEntry.line(), firstEntry.col(), stack.addToLiteralPath(ENTRY, PATH_ARG), resource != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOFIRSTRESOURCE)) {
String id = resource.getNamedChildValue(ID); String id = resource.getNamedChildValue(ID);
ok = validateDocument(errors, bundle, entries, resource, firstStack.push(resource, -1, null, null), fullUrl, id) && ok; ok = validateDocument(errors, bundle, entries, resource, firstStack.push(resource, -1, null, null), fullUrl, id) && ok;
} }
@ -73,7 +73,7 @@ public class BundleValidator extends BaseValidator {
if (type.equals(MESSAGE)) { if (type.equals(MESSAGE)) {
Element resource = firstEntry.getNamedChild(RESOURCE); Element resource = firstEntry.getNamedChild(RESOURCE);
String id = resource.getNamedChildValue(ID); String id = resource.getNamedChildValue(ID);
if (rule(errors, IssueType.INVALID, firstEntry.line(), firstEntry.col(), stack.addToLiteralPath(ENTRY, PATH_ARG), resource != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOFIRSTRESOURCE)) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, firstEntry.line(), firstEntry.col(), stack.addToLiteralPath(ENTRY, PATH_ARG), resource != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_NOFIRSTRESOURCE)) {
ok = validateMessage(errors, entries, resource, firstStack.push(resource, -1, null, null), fullUrl, id) && ok; ok = validateMessage(errors, entries, resource, firstStack.push(resource, -1, null, null), fullUrl, id) && ok;
} }
ok = checkAllInterlinked(errors, entries, stack, bundle, VersionUtilities.isR5Ver(context.getVersion())) && ok; ok = checkAllInterlinked(errors, entries, stack, bundle, VersionUtilities.isR5Ver(context.getVersion())) && ok;
@ -82,7 +82,7 @@ public class BundleValidator extends BaseValidator {
checkSearchSet(errors, bundle, entries, stack); checkSearchSet(errors, bundle, entries, stack);
} }
// We do not yet have rules requiring that the id and fullUrl match when dealing with messaging Bundles // We do not yet have rules requiring that the id and fullUrl match when dealing with messaging Bundles
// validateResourceIds(errors, entries, stack); // validateResourceIds(errors, UNKNOWN_DATE_TIME, entries, stack);
} }
int count = 0; int count = 0;
@ -97,12 +97,12 @@ public class BundleValidator extends BaseValidator {
String id = getIdForEntry(entry); String id = getIdForEntry(entry);
if (url != null) { if (url != null) {
if (!(!url.equals(fullUrl) || (url.matches(uriRegexForVersion()) && url.endsWith("/" + id))) && !isV3orV2Url(url)) if (!(!url.equals(fullUrl) || (url.matches(uriRegexForVersion()) && url.endsWith("/" + id))) && !isV3orV2Url(url))
ok = rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath(ENTRY, PATH_ARG), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_MISMATCHIDURL, url, fullUrl, id) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath(ENTRY, PATH_ARG), false, I18nConstants.BUNDLE_BUNDLE_ENTRY_MISMATCHIDURL, url, fullUrl, id) && ok;
ok = rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath(ENTRY, PATH_ARG), !url.equals(fullUrl) || serverBase == null || (url.equals(Utilities.pathURL(serverBase, entry.getNamedChild(RESOURCE).fhirType(), id))), I18nConstants.BUNDLE_BUNDLE_ENTRY_CANONICAL, url, fullUrl) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath(ENTRY, PATH_ARG), !url.equals(fullUrl) || serverBase == null || (url.equals(Utilities.pathURL(serverBase, entry.getNamedChild(RESOURCE).fhirType(), id))), I18nConstants.BUNDLE_BUNDLE_ENTRY_CANONICAL, url, fullUrl) && ok;
} }
if (!VersionUtilities.isR2Ver(context.getVersion())) { if (!VersionUtilities.isR2Ver(context.getVersion())) {
ok = rule(errors, IssueType.INVALID, entry.line(), entry.col(), estack.getLiteralPath(), fullUrlOptional || fullUrl != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_FULLURL_REQUIRED) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, entry.line(), entry.col(), estack.getLiteralPath(), fullUrlOptional || fullUrl != null, I18nConstants.BUNDLE_BUNDLE_ENTRY_FULLURL_REQUIRED) && ok;
} }
// check bundle profile requests // check bundle profile requests
if (entry.hasChild(RESOURCE)) { if (entry.hasChild(RESOURCE)) {
@ -118,7 +118,7 @@ public class BundleValidator extends BaseValidator {
Element res = entry.getNamedChild(RESOURCE); Element res = entry.getNamedChild(RESOURCE);
NodeStack rstack = estack.push(res, -1, null, null); NodeStack rstack = estack.push(res, -1, null, null);
if (validator.isCrumbTrails()) { if (validator.isCrumbTrails()) {
res.addMessage(signpost(errors, IssueType.INFORMATIONAL, res.line(), res.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM, defn.getUrl())); res.addMessage(signpost(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, res.line(), res.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_BUNDLE_PARAM, defn.getUrl()));
} }
stack.resetIds(); stack.resetIds();
ok = validator.startInner(hostContext, errors, res, res, defn, rstack, false, pct, mode) && ok; ok = validator.startInner(hostContext, errors, res, res, defn, rstack, false, pct, mode) && ok;
@ -140,11 +140,11 @@ public class BundleValidator extends BaseValidator {
Element selfLink = getSelfLink(links); Element selfLink = getSelfLink(links);
List<String> types = new ArrayList<>(); List<String> types = new ArrayList<>();
if (selfLink == null) { if (selfLink == null) {
warning(errors, IssueType.INVALID, bundle.line(), bundle.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_SEARCH_NOSELF); warning(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_SEARCH_NOSELF);
} else { } else {
readSearchResourceTypes(selfLink.getNamedChildValue("url"), types); readSearchResourceTypes(selfLink.getNamedChildValue("url"), types);
if (types.size() == 0) { if (types.size() == 0) {
hint(errors, IssueType.INVALID, bundle.line(), bundle.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_SEARCH_SELF_NOT_UNDERSTOOD); hint(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), stack.getLiteralPath(), false, I18nConstants.BUNDLE_SEARCH_SELF_NOT_UNDERSTOOD);
} }
} }
@ -157,19 +157,19 @@ public class BundleValidator extends BaseValidator {
NodeStack estack = stack.push(entry, count, null, null); NodeStack estack = stack.push(entry, count, null, null);
count++; count++;
Element res = entry.getNamedChild("resource"); Element res = entry.getNamedChild("resource");
if (rule(errors, IssueType.INVALID, bundle.line(), bundle.col(), estack.getLiteralPath(), res != null, I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE)) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), estack.getLiteralPath(), res != null, I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE)) {
NodeStack rstack = estack.push(res, -1, null, null); NodeStack rstack = estack.push(res, -1, null, null);
String rt = res.fhirType(); String rt = res.fhirType();
Boolean ok = checkSearchType(types, rt); Boolean ok = checkSearchType(types, rt);
if (ok == null) { if (ok == null) {
typeProblem = true; typeProblem = true;
hint(errors, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), selfLink == null, I18nConstants.BUNDLE_SEARCH_ENTRY_TYPE_NOT_SURE); hint(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), selfLink == null, I18nConstants.BUNDLE_SEARCH_ENTRY_TYPE_NOT_SURE);
String id = res.getNamedChildValue("id"); String id = res.getNamedChildValue("id");
warning(errors, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), id != null || "OperationOutcome".equals(rt), I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE_ID); warning(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), id != null || "OperationOutcome".equals(rt), I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE_ID);
} else if (ok) { } else if (ok) {
if (!"OperationOutcome".equals(rt)) { if (!"OperationOutcome".equals(rt)) {
String id = res.getNamedChildValue("id"); String id = res.getNamedChildValue("id");
warning(errors, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), id != null, I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE_ID); warning(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), id != null, I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE_ID);
if (rtype != null && !rt.equals(rtype)) { if (rtype != null && !rt.equals(rtype)) {
typeProblem = true; typeProblem = true;
} else if (rtype == null) { } else if (rtype == null) {
@ -178,14 +178,14 @@ public class BundleValidator extends BaseValidator {
} }
} else { } else {
typeProblem = true; typeProblem = true;
warning(errors, IssueType.INVALID, bundle.line(), bundle.col(), estack.getLiteralPath(), false, I18nConstants.BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_NO_MODE, rt, types); warning(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), estack.getLiteralPath(), false, I18nConstants.BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_NO_MODE, rt, types);
} }
} }
} }
if (typeProblem) { if (typeProblem) {
warning(errors, IssueType.INVALID, bundle.line(), bundle.col(), stack.getLiteralPath(), !typeProblem, I18nConstants.BUNDLE_SEARCH_NO_MODE); warning(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), stack.getLiteralPath(), !typeProblem, I18nConstants.BUNDLE_SEARCH_NO_MODE);
} else { } else {
hint(errors, IssueType.INVALID, bundle.line(), bundle.col(), stack.getLiteralPath(), !typeProblem, I18nConstants.BUNDLE_SEARCH_NO_MODE); hint(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), stack.getLiteralPath(), !typeProblem, I18nConstants.BUNDLE_SEARCH_NO_MODE);
} }
} else { } else {
int count = 0; int count = 0;
@ -198,19 +198,19 @@ public class BundleValidator extends BaseValidator {
if (s != null) { if (s != null) {
sm = s.getNamedChildValue("mode"); sm = s.getNamedChildValue("mode");
} }
warning(errors, IssueType.INVALID, bundle.line(), bundle.col(), estack.getLiteralPath(), sm != null, I18nConstants.BUNDLE_SEARCH_NO_MODE); warning(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), estack.getLiteralPath(), sm != null, I18nConstants.BUNDLE_SEARCH_NO_MODE);
if (rule(errors, IssueType.INVALID, bundle.line(), bundle.col(), estack.getLiteralPath(), res != null, I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE)) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), estack.getLiteralPath(), res != null, I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE)) {
NodeStack rstack = estack.push(res, -1, null, null); NodeStack rstack = estack.push(res, -1, null, null);
String rt = res.fhirType(); String rt = res.fhirType();
String id = res.getNamedChildValue("id"); String id = res.getNamedChildValue("id");
if (sm != null) { if (sm != null) {
if ("match".equals(sm)) { if ("match".equals(sm)) {
rule(errors, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), id != null, I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE_ID); rule(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), id != null, I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE_ID);
rule(errors, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), types.size() == 0 || checkSearchType(types, rt), I18nConstants.BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_MODE, rt, types); rule(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), types.size() == 0 || checkSearchType(types, rt), I18nConstants.BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_MODE, rt, types);
} else if ("include".equals(sm)) { } else if ("include".equals(sm)) {
rule(errors, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), id != null, I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE_ID); rule(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), id != null, I18nConstants.BUNDLE_SEARCH_ENTRY_NO_RESOURCE_ID);
} else { // outcome } else { // outcome
rule(errors, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), "OperationOutcome".equals(rt), I18nConstants.BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_OUTCOME, rt); rule(errors, NO_RULE_DATE, IssueType.INVALID, bundle.line(), bundle.col(), rstack.getLiteralPath(), "OperationOutcome".equals(rt), I18nConstants.BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_OUTCOME, rt);
} }
} }
} }
@ -289,7 +289,7 @@ public class BundleValidator extends BaseValidator {
private boolean validateDocument(List<ValidationMessage> errors, Element bundle, List<Element> entries, Element composition, NodeStack stack, String fullUrl, String id) { private boolean validateDocument(List<ValidationMessage> errors, Element bundle, List<Element> entries, Element composition, NodeStack stack, String fullUrl, String id) {
boolean ok = true; boolean ok = true;
// first entry must be a composition // first entry must be a composition
if (rule(errors, IssueType.INVALID, composition.line(), composition.col(), stack.getLiteralPath(), composition.getType().equals("Composition"), I18nConstants.BUNDLE_BUNDLE_ENTRY_DOCUMENT)) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, composition.line(), composition.col(), stack.getLiteralPath(), composition.getType().equals("Composition"), I18nConstants.BUNDLE_BUNDLE_ENTRY_DOCUMENT)) {
// the composition subject etc references must resolve in the bundle // the composition subject etc references must resolve in the bundle
ok = validateDocumentReference(errors, bundle, entries, composition, stack, fullUrl, id, false, "subject", "Composition") && ok; ok = validateDocumentReference(errors, bundle, entries, composition, stack, fullUrl, id, false, "subject", "Composition") && ok;
@ -368,7 +368,7 @@ public class BundleValidator extends BaseValidator {
private boolean validateMessage(List<ValidationMessage> errors, List<Element> entries, Element messageHeader, NodeStack stack, String fullUrl, String id) { private boolean validateMessage(List<ValidationMessage> errors, List<Element> entries, Element messageHeader, NodeStack stack, String fullUrl, String id) {
boolean ok = true; boolean ok = true;
// first entry must be a messageheader // first entry must be a messageheader
if (rule(errors, IssueType.INVALID, messageHeader.line(), messageHeader.col(), stack.getLiteralPath(), messageHeader.getType().equals("MessageHeader"), I18nConstants.VALIDATION_BUNDLE_MESSAGE)) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, messageHeader.line(), messageHeader.col(), stack.getLiteralPath(), messageHeader.getType().equals("MessageHeader"), I18nConstants.VALIDATION_BUNDLE_MESSAGE)) {
List<Element> elements = messageHeader.getChildren("focus"); List<Element> elements = messageHeader.getChildren("focus");
for (Element elem : elements) for (Element elem : elements)
ok = validateBundleReference(errors, messageHeader, entries, elem, "MessageHeader Data", stack.push(elem, -1, null, null), fullUrl, "MessageHeader", id) && ok; ok = validateBundleReference(errors, messageHeader, entries, elem, "MessageHeader Data", stack.push(elem, -1, null, null), fullUrl, "MessageHeader", id) && ok;
@ -385,7 +385,7 @@ public class BundleValidator extends BaseValidator {
if (ref != null && !Utilities.noString(reference) && !reference.startsWith("#")) { if (ref != null && !Utilities.noString(reference) && !reference.startsWith("#")) {
Element target = resolveInBundle(bundle, entries, reference, fullUrl, type, id); Element target = resolveInBundle(bundle, entries, reference, fullUrl, type, id);
return rule(errors, IssueType.INVALID, ref.line(), ref.col(), stack.addToLiteralPath("reference"), target != null, return rule(errors, NO_RULE_DATE, IssueType.INVALID, ref.line(), ref.col(), stack.addToLiteralPath("reference"), target != null,
I18nConstants.BUNDLE_BUNDLE_ENTRY_NOTFOUND, reference, name); I18nConstants.BUNDLE_BUNDLE_ENTRY_NOTFOUND, reference, name);
} }
return true; return true;
@ -409,7 +409,7 @@ public class BundleValidator extends BaseValidator {
boolean ok = bundle.hasChild(META) boolean ok = bundle.hasChild(META)
&& bundle.getNamedChild(META).hasChild(LAST_UPDATED) && bundle.getNamedChild(META).hasChild(LAST_UPDATED)
&& bundle.getNamedChild(META).getNamedChild(LAST_UPDATED).hasValue(); && bundle.getNamedChild(META).getNamedChild(LAST_UPDATED).hasValue();
ruleHtml(errors, IssueType.REQUIRED, stack.getLiteralPath(), ok, I18nConstants.DOCUMENT_DATE_REQUIRED, I18nConstants.DOCUMENT_DATE_REQUIRED_HTML); ruleHtml(errors, NO_RULE_DATE, IssueType.REQUIRED, stack.getLiteralPath(), ok, I18nConstants.DOCUMENT_DATE_REQUIRED, I18nConstants.DOCUMENT_DATE_REQUIRED_HTML);
return ok; return ok;
} }
@ -460,7 +460,7 @@ public class BundleValidator extends BaseValidator {
} }
} }
if (add) { if (add) {
warning(errors, IssueType.INFORMATIONAL, e.getEntry().line(), e.getEntry().col(), warning(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, e.getEntry().line(), e.getEntry().col(),
stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), isExpectedToBeReverse(e.getResource().fhirType()), stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), isExpectedToBeReverse(e.getResource().fhirType()),
I18nConstants.BUNDLE_BUNDLE_ENTRY_REVERSE, (e.getEntry().getChildValue(FULL_URL) != null ? "'" + e.getEntry().getChildValue(FULL_URL) + "'" : "")); I18nConstants.BUNDLE_BUNDLE_ENTRY_REVERSE, (e.getEntry().getChildValue(FULL_URL) != null ? "'" + e.getEntry().getChildValue(FULL_URL) + "'" : ""));
// System.out.println("Found reverse links for "+e.getIndex()); // System.out.println("Found reverse links for "+e.getIndex());
@ -475,9 +475,9 @@ public class BundleValidator extends BaseValidator {
for (EntrySummary e : entryList) { for (EntrySummary e : entryList) {
Element entry = e.getEntry(); Element entry = e.getEntry();
if (isError) { if (isError) {
ok = rule(errors, IssueType.INFORMATIONAL, entry.line(), entry.col(), stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), visited.contains(e), I18nConstants.BUNDLE_BUNDLE_ENTRY_ORPHAN, (entry.getChildValue(FULL_URL) != null ? "'" + entry.getChildValue(FULL_URL) + "'" : "")) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, entry.line(), entry.col(), stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), visited.contains(e), I18nConstants.BUNDLE_BUNDLE_ENTRY_ORPHAN, (entry.getChildValue(FULL_URL) != null ? "'" + entry.getChildValue(FULL_URL) + "'" : "")) && ok;
} else { } else {
warning(errors, IssueType.INFORMATIONAL, entry.line(), entry.col(), stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), visited.contains(e), I18nConstants.BUNDLE_BUNDLE_ENTRY_ORPHAN, (entry.getChildValue(FULL_URL) != null ? "'" + entry.getChildValue(FULL_URL) + "'" : "")); warning(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, entry.line(), entry.col(), stack.addToLiteralPath(ENTRY + '[' + (i + 1) + ']'), visited.contains(e), I18nConstants.BUNDLE_BUNDLE_ENTRY_ORPHAN, (entry.getChildValue(FULL_URL) != null ? "'" + entry.getChildValue(FULL_URL) + "'" : ""));
} }
i++; i++;
} }
@ -534,7 +534,7 @@ public class BundleValidator extends BaseValidator {
} else if (fullUrl.startsWith("urn:uuid") || fullUrl.startsWith("urn:oid")) { } else if (fullUrl.startsWith("urn:uuid") || fullUrl.startsWith("urn:oid")) {
urlId = fullUrl.substring(fullUrl.lastIndexOf(':') + 1); urlId = fullUrl.substring(fullUrl.lastIndexOf(':') + 1);
} }
rule(errors, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry[" + i + "]"), urlId.equals(id), I18nConstants.BUNDLE_BUNDLE_ENTRY_IDURLMISMATCH, id, fullUrl); rule(errors, NO_RULE_DATE, IssueType.INVALID, entry.line(), entry.col(), stack.addToLiteralPath("entry[" + i + "]"), urlId.equals(id), I18nConstants.BUNDLE_BUNDLE_ENTRY_IDURLMISMATCH, id, fullUrl);
} }
i++; i++;
} }

View File

@ -44,7 +44,7 @@ public class CodeSystemValidator extends BaseValidator {
String vsu = cs.getNamedChildValue("valueSet"); String vsu = cs.getNamedChildValue("valueSet");
if (!Utilities.noString(vsu)) { if (!Utilities.noString(vsu)) {
hint(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), "complete".equals(content), I18nConstants.CODESYSTEM_CS_NO_VS_NOTCOMPLETE); hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), "complete".equals(content), I18nConstants.CODESYSTEM_CS_NO_VS_NOTCOMPLETE);
ValueSet vs; ValueSet vs;
try { try {
vs = context.fetchResourceWithException(ValueSet.class, vsu); vs = context.fetchResourceWithException(ValueSet.class, vsu);
@ -52,14 +52,14 @@ public class CodeSystemValidator extends BaseValidator {
vs = null; vs = null;
} }
if (vs != null) { if (vs != null) {
if (rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs.hasCompose(), I18nConstants.CODESYSTEM_CS_VS_INVALID, url, vsu)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs.hasCompose(), I18nConstants.CODESYSTEM_CS_VS_INVALID, url, vsu)) {
if (rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs.getCompose().getInclude().size() == 1, I18nConstants.CODESYSTEM_CS_VS_INVALID, url, vsu)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs.getCompose().getInclude().size() == 1, I18nConstants.CODESYSTEM_CS_VS_INVALID, url, vsu)) {
if (rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs.getCompose().getInclude().get(0).getSystem().equals(url), I18nConstants.CODESYSTEM_CS_VS_WRONGSYSTEM, url, vsu, vs.getCompose().getInclude().get(0).getSystem())) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs.getCompose().getInclude().get(0).getSystem().equals(url), I18nConstants.CODESYSTEM_CS_VS_WRONGSYSTEM, url, vsu, vs.getCompose().getInclude().get(0).getSystem())) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), !vs.getCompose().getInclude().get(0).hasValueSet() ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !vs.getCompose().getInclude().get(0).hasValueSet()
&& !vs.getCompose().getInclude().get(0).hasConcept() && !vs.getCompose().getInclude().get(0).hasFilter(), I18nConstants.CODESYSTEM_CS_VS_INCLUDEDETAILS, url, vsu) && ok; && !vs.getCompose().getInclude().get(0).hasConcept() && !vs.getCompose().getInclude().get(0).hasFilter(), I18nConstants.CODESYSTEM_CS_VS_INCLUDEDETAILS, url, vsu) && ok;
if (vs.hasExpansion()) { if (vs.hasExpansion()) {
int count = countConcepts(cs); int count = countConcepts(cs);
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs.getExpansion().getContains().size() == count, I18nConstants.CODESYSTEM_CS_VS_EXP_MISMATCH, url, vsu, count, vs.getExpansion().getContains().size()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs.getExpansion().getContains().size() == count, I18nConstants.CODESYSTEM_CS_VS_EXP_MISMATCH, url, vsu, count, vs.getExpansion().getContains().size()) && ok;
} }
} else { } else {
ok = false; ok = false;
@ -83,7 +83,7 @@ public class CodeSystemValidator extends BaseValidator {
} }
} else { } else {
if (cs.hasChildren("concept")) { if (cs.hasChildren("concept")) {
warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_SUPP_CANT_CHECK, supp); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_SUPP_CANT_CHECK, supp);
} }
} }
} }
@ -99,29 +99,29 @@ public class CodeSystemValidator extends BaseValidator {
if (parent.isForPublication()) { if (parent.isForPublication()) {
if (isHL7(cs)) { if (isHL7(cs)) {
boolean ok = true; boolean ok = true;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("url"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "url") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("url"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "url") && ok;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("version"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "version") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("version"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "version") && ok;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("title"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "title") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("title"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "title") && ok;
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("name"), I18nConstants.CODESYSTEM_SHAREABLE_EXTRA_MISSING_HL7, "name"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("name"), I18nConstants.CODESYSTEM_SHAREABLE_EXTRA_MISSING_HL7, "name");
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("status"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "status") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("status"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "status") && ok;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("experimental"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "experimental") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("experimental"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "experimental") && ok;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("description"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "description") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("description"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "description") && ok;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("content"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "content") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("content"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "content") && ok;
if (!"supplement".equals(cs.getChildValue("content"))) { if (!"supplement".equals(cs.getChildValue("content"))) {
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("caseSensitive"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "caseSensitive") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("caseSensitive"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING_HL7, "caseSensitive") && ok;
} }
return ok; return ok;
} else { } else {
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("url"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "url"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("url"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "url");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("version"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "version"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("version"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "version");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("title"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "title"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("title"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "title");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("name"), I18nConstants.CODESYSTEM_SHAREABLE_EXTRA_MISSING, "name"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("name"), I18nConstants.CODESYSTEM_SHAREABLE_EXTRA_MISSING, "name");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("status"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "status"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("status"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "status");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("experimental"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "experimental"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("experimental"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "experimental");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("description"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "description"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("description"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "description");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("content"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "content"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("content"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "content");
if (!"supplement".equals(cs.getChildValue("content"))) { if (!"supplement".equals(cs.getChildValue("content"))) {
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("caseSensitive"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "caseSensitive"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("caseSensitive"), I18nConstants.CODESYSTEM_SHAREABLE_MISSING, "caseSensitive");
} }
} }
} }
@ -132,15 +132,15 @@ public class CodeSystemValidator extends BaseValidator {
if (isSupplement) { if (isSupplement) {
if (!"supplement".equals(content)) { if (!"supplement".equals(content)) {
NodeStack s = stack.push(cs.getNamedChild("content"), -1, null, null); NodeStack s = stack.push(cs.getNamedChild("content"), -1, null, null);
rule(errors, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_WRONG); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_WRONG);
} }
if (!Utilities.noString(caseSensitive)) { if (!Utilities.noString(caseSensitive)) {
NodeStack s = stack.push(cs.getNamedChild("caseSensitive"), -1, null, null); NodeStack s = stack.push(cs.getNamedChild("caseSensitive"), -1, null, null);
rule(errors, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL, "caseSensitive"); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL, "caseSensitive");
} }
if (!Utilities.noString(hierarchyMeaning)) { if (!Utilities.noString(hierarchyMeaning)) {
NodeStack s = stack.push(cs.getNamedChild("hierarchyMeaning"), -1, null, null); NodeStack s = stack.push(cs.getNamedChild("hierarchyMeaning"), -1, null, null);
rule(errors, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL, "hierarchyMeaning"); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL, "hierarchyMeaning");
} }
} else { } else {
@ -152,13 +152,13 @@ public class CodeSystemValidator extends BaseValidator {
s = stack.push(c, -1, null, null); s = stack.push(c, -1, null, null);
} }
if (isHL7) { if (isHL7) {
rule(errors, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_MISSING_ELEMENT_SHALL, "content"); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_MISSING_ELEMENT_SHALL, "content");
} else { } else {
warning(errors, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_NONHL7_MISSING_ELEMENT, "content"); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_NONHL7_MISSING_ELEMENT, "content");
} }
} else if ("supplement".equals(content)) { } else if ("supplement".equals(content)) {
NodeStack s = stack.push(cs.getNamedChild("content"), -1, null, null); NodeStack s = stack.push(cs.getNamedChild("content"), -1, null, null);
rule(errors, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_MISSING); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_PRESENT_ELEMENT_SUPPL_MISSING);
} }
if (Utilities.noString(caseSensitive)) { if (Utilities.noString(caseSensitive)) {
NodeStack s = stack; NodeStack s = stack;
@ -167,9 +167,9 @@ public class CodeSystemValidator extends BaseValidator {
s = stack.push(c, -1, null, null); s = stack.push(c, -1, null, null);
} }
if (isHL7) { if (isHL7) {
warning(errors, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_MISSING_ELEMENT_SHOULD, "caseSensitive"); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_MISSING_ELEMENT_SHOULD, "caseSensitive");
} else { } else {
hint(errors, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_NONHL7_MISSING_ELEMENT, "caseSensitive"); hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_NONHL7_MISSING_ELEMENT, "caseSensitive");
} }
} }
if (Utilities.noString(hierarchyMeaning) && hasHeirarchy(cs)) { if (Utilities.noString(hierarchyMeaning) && hasHeirarchy(cs)) {
@ -179,9 +179,9 @@ public class CodeSystemValidator extends BaseValidator {
s = stack.push(c, -1, null, null); s = stack.push(c, -1, null, null);
} }
if (isHL7) { if (isHL7) {
warning(errors, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_MISSING_ELEMENT_SHOULD, "hierarchyMeaning"); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_HL7_MISSING_ELEMENT_SHOULD, "hierarchyMeaning");
} else { } else {
hint(errors, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_NONHL7_MISSING_ELEMENT, "hierarchyMeaning"); hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, s.getLiteralPath(), false, I18nConstants.CODESYSTEM_CS_NONHL7_MISSING_ELEMENT, "hierarchyMeaning");
} }
} }
} }
@ -201,7 +201,7 @@ public class CodeSystemValidator extends BaseValidator {
String code = concept.getChildValue("code"); String code = concept.getChildValue("code");
if (!Utilities.noString(code)) { if (!Utilities.noString(code)) {
org.hl7.fhir.r5.context.IWorkerContext.ValidationResult res = context.validateCode(options, systemFromCanonical(supp), versionFromCanonical(supp), code, null); org.hl7.fhir.r5.context.IWorkerContext.ValidationResult res = context.validateCode(options, systemFromCanonical(supp), versionFromCanonical(supp), code, null);
return rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), res.isOk(), I18nConstants.CODESYSTEM_CS_SUPP_INVALID_CODE, supp, code); return rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), res.isOk(), I18nConstants.CODESYSTEM_CS_SUPP_INVALID_CODE, supp, code);
} else { } else {
return true; return true;
} }

View File

@ -61,31 +61,31 @@ public class MeasureValidator extends BaseValidator {
String ref = lib.isPrimitive() ? lib.primitiveValue() : lib.getChildValue("reference"); String ref = lib.isPrimitive() ? lib.primitiveValue() : lib.getChildValue("reference");
if (!Utilities.noString(ref)) { if (!Utilities.noString(ref)) {
Library l = context.fetchResource(Library.class, ref); Library l = context.fetchResource(Library.class, ref);
if (hint(errors, IssueType.NOTFOUND, lib.line(), lib.col(), stack.getLiteralPath(), l != null, I18nConstants.MEASURE_M_LIB_UNKNOWN, ref)) { if (hint(errors, NO_RULE_DATE, IssueType.NOTFOUND, lib.line(), lib.col(), stack.getLiteralPath(), l != null, I18nConstants.MEASURE_M_LIB_UNKNOWN, ref)) {
mctxt.seeLibrary(l); mctxt.seeLibrary(l);
} }
} }
} }
List<Element> groups = element.getChildrenByName("group"); List<Element> groups = element.getChildrenByName("group");
if (warning(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), groups.size() > 0, I18nConstants.MEASURE_M_NO_GROUPS)) { if (warning(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), groups.size() > 0, I18nConstants.MEASURE_M_NO_GROUPS)) {
int c = 0; int c = 0;
for (Element group : groups) { for (Element group : groups) {
NodeStack ns = stack.push(group, c, null, null); NodeStack ns = stack.push(group, c, null, null);
warning(errors, IssueType.REQUIRED, group.line(), group.col(), ns.getLiteralPath(), groups.size() ==1 || group.hasChild("code"), I18nConstants.MEASURE_M_GROUP_CODE); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, group.line(), group.col(), ns.getLiteralPath(), groups.size() ==1 || group.hasChild("code"), I18nConstants.MEASURE_M_GROUP_CODE);
warning(errors, IssueType.REQUIRED, group.line(), group.col(), ns.getLiteralPath(), group.hasChildren("population"), I18nConstants.MEASURE_M_GROUP_POP); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, group.line(), group.col(), ns.getLiteralPath(), group.hasChildren("population"), I18nConstants.MEASURE_M_GROUP_POP);
int c1 = 0; int c1 = 0;
List<Element> pl = group.getChildrenByName("population"); List<Element> pl = group.getChildrenByName("population");
for (Element p : pl) { for (Element p : pl) {
NodeStack ns2 = ns.push(p, c1, null, null); NodeStack ns2 = ns.push(p, c1, null, null);
warning(errors, IssueType.REQUIRED, p.line(), p.col(), ns2.getLiteralPath(), pl.size() == 1 || p.hasChild("code"), I18nConstants.MEASURE_M_GROUP_POP_NO_CODE); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, p.line(), p.col(), ns2.getLiteralPath(), pl.size() == 1 || p.hasChild("code"), I18nConstants.MEASURE_M_GROUP_POP_NO_CODE);
c1++; c1++;
} }
c1 = 0; c1 = 0;
List<Element> stl = group.getChildrenByName("stratifier"); List<Element> stl = group.getChildrenByName("stratifier");
for (Element st : stl) { for (Element st : stl) {
NodeStack ns2 = ns.push(st, c1, null, null); NodeStack ns2 = ns.push(st, c1, null, null);
warning(errors, IssueType.REQUIRED, st.line(), st.col(), ns2.getLiteralPath(), stl.size() == 1 || st.hasChild("code"), I18nConstants.MEASURE_M_GROUP_STRATA_NO_CODE); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, st.line(), st.col(), ns2.getLiteralPath(), stl.size() == 1 || st.hasChild("code"), I18nConstants.MEASURE_M_GROUP_STRATA_NO_CODE);
if (st.hasChild("criteria")) { if (st.hasChild("criteria")) {
Element crit = st.getNamedChild("criteria"); Element crit = st.getNamedChild("criteria");
NodeStack nsc = ns2.push(crit, -1, null, null); NodeStack nsc = ns2.push(crit, -1, null, null);
@ -95,7 +95,7 @@ public class MeasureValidator extends BaseValidator {
List<Element> cpl = group.getChildrenByName("component"); List<Element> cpl = group.getChildrenByName("component");
for (Element cp : cpl) { for (Element cp : cpl) {
NodeStack ns3 = ns2.push(cp, c2, null, null); NodeStack ns3 = ns2.push(cp, c2, null, null);
warning(errors, IssueType.REQUIRED, cp.line(), cp.col(), ns3.getLiteralPath(), cpl.size() == 1 || cp.hasChild("code"), I18nConstants.MEASURE_M_GROUP_STRATA_COMP_NO_CODE); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cp.line(), cp.col(), ns3.getLiteralPath(), cpl.size() == 1 || cp.hasChild("code"), I18nConstants.MEASURE_M_GROUP_STRATA_COMP_NO_CODE);
if (cp.hasChild("criteria")) { if (cp.hasChild("criteria")) {
Element crit = cp.getNamedChild("criteria"); Element crit = cp.getNamedChild("criteria");
NodeStack nsc = ns3.push(crit, -1, null, null); NodeStack nsc = ns3.push(crit, -1, null, null);
@ -119,23 +119,23 @@ public class MeasureValidator extends BaseValidator {
boolean ok = true; boolean ok = true;
if (parent.isForPublication()) { if (parent.isForPublication()) {
if (isHL7(cs)) { if (isHL7(cs)) {
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("url"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "url") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("url"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "url") && ok;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("version"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "version") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("version"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "version") && ok;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("name"), I18nConstants.MEASURE_SHAREABLE_EXTRA_MISSING_HL7, "name") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("name"), I18nConstants.MEASURE_SHAREABLE_EXTRA_MISSING_HL7, "name") && ok;
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("title"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "title"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("title"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "title");
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("status"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "status") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("status"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "status") && ok;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("experimental"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "experimental") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("experimental"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "experimental") && ok;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("publisher"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "publisher") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("publisher"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "publisher") && ok;
ok = rule(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("description"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "description") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("description"), I18nConstants.MEASURE_SHAREABLE_MISSING_HL7, "description") && ok;
} else { } else {
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("url"), I18nConstants.MEASURE_SHAREABLE_MISSING, "url"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("url"), I18nConstants.MEASURE_SHAREABLE_MISSING, "url");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("version"), I18nConstants.MEASURE_SHAREABLE_MISSING, "version"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("version"), I18nConstants.MEASURE_SHAREABLE_MISSING, "version");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("name"), I18nConstants.MEASURE_SHAREABLE_EXTRA_MISSING, "name"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("name"), I18nConstants.MEASURE_SHAREABLE_EXTRA_MISSING, "name");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("title"), I18nConstants.MEASURE_SHAREABLE_MISSING, "title"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("title"), I18nConstants.MEASURE_SHAREABLE_MISSING, "title");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("status"), I18nConstants.MEASURE_SHAREABLE_MISSING, "status"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("status"), I18nConstants.MEASURE_SHAREABLE_MISSING, "status");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("experimental"), I18nConstants.MEASURE_SHAREABLE_MISSING, "experimental"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("experimental"), I18nConstants.MEASURE_SHAREABLE_MISSING, "experimental");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("description"), I18nConstants.MEASURE_SHAREABLE_MISSING, "description"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("description"), I18nConstants.MEASURE_SHAREABLE_MISSING, "description");
warning(errors, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("publisher"), I18nConstants.MEASURE_SHAREABLE_MISSING, "publisher"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, cs.line(), cs.col(), stack.getLiteralPath(), cs.hasChild("publisher"), I18nConstants.MEASURE_SHAREABLE_MISSING, "publisher");
} }
} }
return ok; return ok;
@ -148,22 +148,22 @@ public class MeasureValidator extends BaseValidator {
if ("text/cql".equals(mimeType) || "text/cql.identifier".equals(mimeType)) { if ("text/cql".equals(mimeType) || "text/cql.identifier".equals(mimeType)) {
String cqlRef = crit.getChildValue("expression"); String cqlRef = crit.getChildValue("expression");
Library lib = null; Library lib = null;
if (rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), mctxt.libraries().size()> 0, I18nConstants.MEASURE_M_CRITERIA_CQL_NO_LIB)) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), mctxt.libraries().size()> 0, I18nConstants.MEASURE_M_CRITERIA_CQL_NO_LIB)) {
if (cqlRef.contains(".")) { if (cqlRef.contains(".")) {
String name = cqlRef.substring(0, cqlRef.indexOf(".")); String name = cqlRef.substring(0, cqlRef.indexOf("."));
cqlRef = cqlRef.substring(cqlRef.indexOf(".")+1); cqlRef = cqlRef.substring(cqlRef.indexOf(".")+1);
for (Library l : mctxt.libraries()) { for (Library l : mctxt.libraries()) {
if (name.equals(l.getName())) { if (name.equals(l.getName())) {
if (rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), lib == null, I18nConstants.MEASURE_M_CRITERIA_CQL_LIB_DUPL)) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), lib == null, I18nConstants.MEASURE_M_CRITERIA_CQL_LIB_DUPL)) {
lib = l; lib = l;
} else { } else {
ok = false; ok = false;
} }
} }
} }
ok = rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), lib != null, I18nConstants.MEASURE_M_CRITERIA_CQL_LIB_NOT_FOUND, name) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), lib != null, I18nConstants.MEASURE_M_CRITERIA_CQL_LIB_NOT_FOUND, name) && ok;
} else { } else {
if (rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), mctxt.libraries().size() == 1, I18nConstants.MEASURE_M_CRITERIA_CQL_ONLY_ONE_LIB)) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), mctxt.libraries().size() == 1, I18nConstants.MEASURE_M_CRITERIA_CQL_ONLY_ONE_LIB)) {
lib = mctxt.libraries().get(0); lib = mctxt.libraries().get(0);
} else { } else {
ok = false; ok = false;
@ -173,13 +173,13 @@ public class MeasureValidator extends BaseValidator {
ok = false; ok = false;
} }
if (lib != null) { if (lib != null) {
if (rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), lib.hasUserData(MeasureContext.USER_DATA_ELM), I18nConstants.MEASURE_M_CRITERIA_CQL_NO_ELM, lib.getUrl())) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), lib.hasUserData(MeasureContext.USER_DATA_ELM), I18nConstants.MEASURE_M_CRITERIA_CQL_NO_ELM, lib.getUrl())) {
if (lib.getUserData(MeasureContext.USER_DATA_ELM) instanceof String) { if (lib.getUserData(MeasureContext.USER_DATA_ELM) instanceof String) {
ok = rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_CQL_ERROR, lib.getUrl(), lib.getUserString(MeasureContext.USER_DATA_ELM)) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_CQL_ERROR, lib.getUrl(), lib.getUserString(MeasureContext.USER_DATA_ELM)) && ok;
} else if (lib.getUserData(MeasureContext.USER_DATA_ELM) instanceof Document) { } else if (lib.getUserData(MeasureContext.USER_DATA_ELM) instanceof Document) {
org.w3c.dom.Element elm = ((Document)lib.getUserData(MeasureContext.USER_DATA_ELM)).getDocumentElement(); org.w3c.dom.Element elm = ((Document)lib.getUserData(MeasureContext.USER_DATA_ELM)).getDocumentElement();
if (rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), isValidElm(elm), I18nConstants.MEASURE_M_CRITERIA_CQL_ELM_NOT_VALID, lib.getUrl(), cqlRef)) { if (rule(errors, NO_RULE_DATE, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), isValidElm(elm), I18nConstants.MEASURE_M_CRITERIA_CQL_ELM_NOT_VALID, lib.getUrl(), cqlRef)) {
ok = rule(errors, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), hasCqlTarget(elm, cqlRef), I18nConstants.MEASURE_M_CRITERIA_CQL_NOT_FOUND, lib.getUrl(), cqlRef) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, crit.line(), crit.col(), nsc.getLiteralPath(), hasCqlTarget(elm, cqlRef), I18nConstants.MEASURE_M_CRITERIA_CQL_NOT_FOUND, lib.getUrl(), cqlRef) && ok;
} }
} }
} else { } else {
@ -187,11 +187,11 @@ public class MeasureValidator extends BaseValidator {
} }
} }
} else if ("text/fhirpath".equals(mimeType)) { } else if ("text/fhirpath".equals(mimeType)) {
warning(errors, IssueType.REQUIRED, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_UNKNOWN, mimeType); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_UNKNOWN, mimeType);
} else if ("application/x-fhir-query".equals(mimeType)) { } else if ("application/x-fhir-query".equals(mimeType)) {
warning(errors, IssueType.REQUIRED, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_UNKNOWN, mimeType); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_UNKNOWN, mimeType);
} else { } else {
warning(errors, IssueType.REQUIRED, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_UNKNOWN, mimeType); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, crit.line(), crit.col(), nsc.getLiteralPath(), false, I18nConstants.MEASURE_M_CRITERIA_UNKNOWN, mimeType);
} }
} }
return ok; return ok;
@ -233,15 +233,15 @@ public class MeasureValidator extends BaseValidator {
measure = m.getChildValue("reference"); measure = m.getChildValue("reference");
} }
} }
if (hint(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), measure != null, I18nConstants.MEASURE_MR_M_NONE)) { if (hint(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), measure != null, I18nConstants.MEASURE_MR_M_NONE)) {
long t = System.nanoTime(); long t = System.nanoTime();
Measure msrc = measure.startsWith("#") ? loadMeasure(element, measure.substring(1)) : context.fetchResource(Measure.class, measure); Measure msrc = measure.startsWith("#") ? loadMeasure(element, measure.substring(1)) : context.fetchResource(Measure.class, measure);
timeTracker.sd(t); timeTracker.sd(t);
if (warning(errors, IssueType.REQUIRED, m.line(), m.col(), stack.getLiteralPath(), msrc != null, I18nConstants.MEASURE_MR_M_NOTFOUND, measure)) { if (warning(errors, NO_RULE_DATE, IssueType.REQUIRED, m.line(), m.col(), stack.getLiteralPath(), msrc != null, I18nConstants.MEASURE_MR_M_NOTFOUND, measure)) {
boolean inComplete = !"complete".equals(element.getNamedChildValue("status")); boolean inComplete = !"complete".equals(element.getNamedChildValue("status"));
MeasureContext mc = new MeasureContext(msrc, element); MeasureContext mc = new MeasureContext(msrc, element);
NodeStack ns = stack.push(m, -1, m.getProperty().getDefinition(), m.getProperty().getDefinition()); NodeStack ns = stack.push(m, -1, m.getProperty().getDefinition(), m.getProperty().getDefinition());
hint(errors, IssueType.BUSINESSRULE, m.line(), m.col(), ns.getLiteralPath(), Utilities.existsInList(mc.scoring(), "proportion", "ratio", "continuous-variable", "cohort"), I18nConstants.MEASURE_MR_M_SCORING_UNK); hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, m.line(), m.col(), ns.getLiteralPath(), Utilities.existsInList(mc.scoring(), "proportion", "ratio", "continuous-variable", "cohort"), I18nConstants.MEASURE_MR_M_SCORING_UNK);
ok = validateMeasureReportGroups(hostContext, mc, errors, element, stack, inComplete) && ok; ok = validateMeasureReportGroups(hostContext, mc, errors, element, stack, inComplete) && ok;
} }
} }
@ -311,8 +311,8 @@ public class MeasureValidator extends BaseValidator {
NodeStack ns = stack.push(mrg, 0, mrg.getProperty().getDefinition(), mrg.getProperty().getDefinition()); NodeStack ns = stack.push(mrg, 0, mrg.getProperty().getDefinition(), mrg.getProperty().getDefinition());
if (m.groups().get(0).hasCode() && mrg.hasChild("code")) { if (m.groups().get(0).hasCode() && mrg.hasChild("code")) {
CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrg.getNamedChild("code")); CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrg.getNamedChild("code"));
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), hasUseableCode(cc), I18nConstants.MEASURE_MR_GRP_NO_USABLE_CODE)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), hasUseableCode(cc), I18nConstants.MEASURE_MR_GRP_NO_USABLE_CODE)) {
ok = rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), cc.matches(m.groups().get(0).getCode()), I18nConstants.MEASURE_MR_GRP_NO_WRONG_CODE, DataRenderer.display(context, cc), DataRenderer.display(context, m.groups().get(0).getCode())) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), cc.matches(m.groups().get(0).getCode()), I18nConstants.MEASURE_MR_GRP_NO_WRONG_CODE, DataRenderer.display(context, cc), DataRenderer.display(context, m.groups().get(0).getCode())) && ok;
} else { } else {
ok = false; ok = false;
} }
@ -323,10 +323,10 @@ public class MeasureValidator extends BaseValidator {
for (Element mrg : glist) { for (Element mrg : glist) {
NodeStack ns = stack.push(mrg, i, mrg.getProperty().getDefinition(), mrg.getProperty().getDefinition()); NodeStack ns = stack.push(mrg, i, mrg.getProperty().getDefinition(), mrg.getProperty().getDefinition());
CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrg.getNamedChild("code")); CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrg.getNamedChild("code"));
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), cc != null, I18nConstants.MEASURE_MR_GRP_NO_CODE)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), cc != null, I18nConstants.MEASURE_MR_GRP_NO_CODE)) {
MeasureGroupComponent mg = getGroupForCode(cc, m.measure()); MeasureGroupComponent mg = getGroupForCode(cc, m.measure());
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mg != null, I18nConstants.MEASURE_MR_GRP_UNK_CODE)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mg != null, I18nConstants.MEASURE_MR_GRP_UNK_CODE)) {
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !groups.contains(mg), I18nConstants.MEASURE_MR_GRP_DUPL_CODE)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !groups.contains(mg), I18nConstants.MEASURE_MR_GRP_DUPL_CODE)) {
groups.add(mg); groups.add(mg);
ok = validateMeasureReportGroup(hostContext, m, mg, errors, mrg, ns, inProgress) && ok; ok = validateMeasureReportGroup(hostContext, m, mg, errors, mrg, ns, inProgress) && ok;
} else { } else {
@ -343,7 +343,7 @@ public class MeasureValidator extends BaseValidator {
boolean dataCollection = isDataCollection(mr); boolean dataCollection = isDataCollection(mr);
for (MeasureGroupComponent mg : m.groups()) { for (MeasureGroupComponent mg : m.groups()) {
if (!groups.contains(mg)) { if (!groups.contains(mg)) {
ok = rule(errors, IssueType.BUSINESSRULE, mr.line(), mr.col(), stack.getLiteralPath(), groups.contains(mg) || dataCollection, I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, DataRenderer.display(context, mg.getCode())) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mr.line(), mr.col(), stack.getLiteralPath(), groups.contains(mg) || dataCollection, I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, DataRenderer.display(context, mg.getCode())) && ok;
} }
} }
} }
@ -373,7 +373,7 @@ public class MeasureValidator extends BaseValidator {
// cohort - there is no measure score // cohort - there is no measure score
ok = banned(errors, stack, ms, I18nConstants.MEASURE_MR_SCORE_PROHIBITED_MS) && ok; ok = banned(errors, stack, ms, I18nConstants.MEASURE_MR_SCORE_PROHIBITED_MS) && ok;
} else if (Utilities.existsInList(m.scoring(), "proportion", "ratio", "continuous-variable")) { } else if (Utilities.existsInList(m.scoring(), "proportion", "ratio", "continuous-variable")) {
if (rule(errors, IssueType.REQUIRED, mrg.line(), mrg.col(), stack.getLiteralPath(), ms != null, I18nConstants.MEASURE_MR_SCORE_REQUIRED, m.scoring())) { if (rule(errors, NO_RULE_DATE, IssueType.REQUIRED, mrg.line(), mrg.col(), stack.getLiteralPath(), ms != null, I18nConstants.MEASURE_MR_SCORE_REQUIRED, m.scoring())) {
NodeStack ns = stack.push(ms, -1, ms.getProperty().getDefinition(), ms.getProperty().getDefinition()); NodeStack ns = stack.push(ms, -1, ms.getProperty().getDefinition(), ms.getProperty().getDefinition());
Element v = ms.getNamedChild("value"); Element v = ms.getNamedChild("value");
// TODO: this is a DEQM special and should be handled differently // TODO: this is a DEQM special and should be handled differently
@ -387,11 +387,11 @@ public class MeasureValidator extends BaseValidator {
ok = banned(errors, ns, ms, "unit", I18nConstants.MEASURE_MR_SCORE_UNIT_PROHIBITED, "proportion"); ok = banned(errors, ns, ms, "unit", I18nConstants.MEASURE_MR_SCORE_UNIT_PROHIBITED, "proportion");
ok = banned(errors, ns, ms, "system", I18nConstants.MEASURE_MR_SCORE_UNIT_PROHIBITED, "proportion"); ok = banned(errors, ns, ms, "system", I18nConstants.MEASURE_MR_SCORE_UNIT_PROHIBITED, "proportion");
ok = banned(errors, ns, ms, "code", I18nConstants.MEASURE_MR_SCORE_UNIT_PROHIBITED, "proportion"); ok = banned(errors, ns, ms, "code", I18nConstants.MEASURE_MR_SCORE_UNIT_PROHIBITED, "proportion");
if (rule(errors, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED, "proportion")) { if (rule(errors, NO_RULE_DATE, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED, "proportion")) {
try { try {
BigDecimal dec = new BigDecimal(v.primitiveValue()); BigDecimal dec = new BigDecimal(v.primitiveValue());
NodeStack nsv = ns.push(v, -1, v.getProperty().getDefinition(), v.getProperty().getDefinition()); NodeStack nsv = ns.push(v, -1, v.getProperty().getDefinition(), v.getProperty().getDefinition());
ok = rule(errors, IssueType.REQUIRED, v.line(), v.col(), nsv.getLiteralPath(), dec.compareTo(new BigDecimal(0)) >= 0 && dec.compareTo(new BigDecimal(1)) <= 0, I18nConstants.MEASURE_MR_SCORE_VALUE_INVALID_01) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, v.line(), v.col(), nsv.getLiteralPath(), dec.compareTo(new BigDecimal(0)) >= 0 && dec.compareTo(new BigDecimal(1)) <= 0, I18nConstants.MEASURE_MR_SCORE_VALUE_INVALID_01) && ok;
} catch (Exception e) { } catch (Exception e) {
// nothing - will have caused an error elsewhere // nothing - will have caused an error elsewhere
} }
@ -400,48 +400,48 @@ public class MeasureValidator extends BaseValidator {
} }
} else if ("ratio".equals(m.scoring())) { } else if ("ratio".equals(m.scoring())) {
// ratio - score is a number with no value constraints, and maybe with a unit (perhaps constrained by extension) // ratio - score is a number with no value constraints, and maybe with a unit (perhaps constrained by extension)
if (rule(errors, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED, "ratio")) { if (rule(errors, NO_RULE_DATE, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED, "ratio")) {
Element unit = ms.getNamedChild("code"); Element unit = ms.getNamedChild("code");
Coding c = m.measure().hasExtension(ToolingExtensions.EXT_Q_UNIT) ? (Coding) m.measure().getExtensionByUrl(ToolingExtensions.EXT_Q_UNIT).getValue() : null; Coding c = m.measure().hasExtension(ToolingExtensions.EXT_Q_UNIT) ? (Coding) m.measure().getExtensionByUrl(ToolingExtensions.EXT_Q_UNIT).getValue() : null;
if (unit != null) { if (unit != null) {
if (c != null) { if (c != null) {
NodeStack nsc = ns.push(unit, -1, unit.getProperty().getDefinition(), unit.getProperty().getDefinition()); NodeStack nsc = ns.push(unit, -1, unit.getProperty().getDefinition(), unit.getProperty().getDefinition());
ok = rule(errors, IssueType.CODEINVALID, unit.line(), unit.col(), nsc.getLiteralPath(), c.getCode().equals(unit.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getCode()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, unit.line(), unit.col(), nsc.getLiteralPath(), c.getCode().equals(unit.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getCode()) && ok;
Element system = ms.getNamedChild("system"); Element system = ms.getNamedChild("system");
if (system == null) { if (system == null) {
NodeStack nss = system == null ? ns : ns.push(system, -1, system.getProperty().getDefinition(), system.getProperty().getDefinition()); NodeStack nss = system == null ? ns : ns.push(system, -1, system.getProperty().getDefinition(), system.getProperty().getDefinition());
ok = rule(errors, IssueType.CODEINVALID, system.line(), system.col(), nss.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, system.line(), system.col(), nss.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem()) && ok;
} else { } else {
ok = rule(errors, IssueType.CODEINVALID, ms.line(), ms.col(), ns.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, ms.line(), ms.col(), ns.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem()) && ok;
} }
} }
} else if (c != null) { } else if (c != null) {
ok = rule(errors, IssueType.NOTFOUND, ms.line(), ms.col(), ns.getLiteralPath(), false, I18nConstants.MEASURE_MR_SCORE_FIXED, DataRenderer.display(context, c)) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, ms.line(), ms.col(), ns.getLiteralPath(), false, I18nConstants.MEASURE_MR_SCORE_FIXED, DataRenderer.display(context, c)) && ok;
} else { } else {
warning(errors, IssueType.NOTFOUND, ms.line(), ms.col(), ns.getLiteralPath(), false, I18nConstants.MEASURE_MR_SCORE_UNIT_REQUIRED, "ratio"); warning(errors, NO_RULE_DATE, IssueType.NOTFOUND, ms.line(), ms.col(), ns.getLiteralPath(), false, I18nConstants.MEASURE_MR_SCORE_UNIT_REQUIRED, "ratio");
} }
} else { } else {
ok = true; ok = true;
} }
} else if ("continuous-variable".equals(m.scoring())) { } else if ("continuous-variable".equals(m.scoring())) {
// continuous-variable - score is a quantity with a unit per the extension // continuous-variable - score is a quantity with a unit per the extension
if (rule(errors, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED, "continuous-variable")) { if (rule(errors, NO_RULE_DATE, IssueType.REQUIRED, ms.line(), ms.col(), ns.getLiteralPath(), v != null, I18nConstants.MEASURE_MR_SCORE_VALUE_REQUIRED, "continuous-variable")) {
Element unit = ms.getNamedChild("code"); Element unit = ms.getNamedChild("code");
Coding c = m.measure().hasExtension(ToolingExtensions.EXT_Q_UNIT) ? (Coding) m.measure().getExtensionByUrl(ToolingExtensions.EXT_Q_UNIT).getValue() : null; Coding c = m.measure().hasExtension(ToolingExtensions.EXT_Q_UNIT) ? (Coding) m.measure().getExtensionByUrl(ToolingExtensions.EXT_Q_UNIT).getValue() : null;
if (unit != null) { if (unit != null) {
if (c != null) { if (c != null) {
NodeStack nsc = ns.push(unit, -1, unit.getProperty().getDefinition(), unit.getProperty().getDefinition()); NodeStack nsc = ns.push(unit, -1, unit.getProperty().getDefinition(), unit.getProperty().getDefinition());
rule(errors, IssueType.CODEINVALID, unit.line(), unit.col(), nsc.getLiteralPath(), c.getCode().equals(unit.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getCode()); rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, unit.line(), unit.col(), nsc.getLiteralPath(), c.getCode().equals(unit.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getCode());
Element system = ms.getNamedChild("system"); Element system = ms.getNamedChild("system");
if (system == null) { if (system == null) {
NodeStack nss = system == null ? ns : ns.push(system, -1, system.getProperty().getDefinition(), system.getProperty().getDefinition()); NodeStack nss = system == null ? ns : ns.push(system, -1, system.getProperty().getDefinition(), system.getProperty().getDefinition());
ok = rule(errors, IssueType.CODEINVALID, system.line(), system.col(), nss.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, system.line(), system.col(), nss.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem()) && ok;
} else { } else {
ok = rule(errors, IssueType.CODEINVALID, ms.line(), ms.col(), ns.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, ms.line(), ms.col(), ns.getLiteralPath(), c.getSystem().equals(system.primitiveValue()), I18nConstants.MEASURE_MR_SCORE_FIXED, c.getSystem()) && ok;
} }
} }
} else if (c != null) { } else if (c != null) {
ok = rule(errors, IssueType.NOTFOUND, ms.line(), ms.col(), ns.getLiteralPath(), false, I18nConstants.MEASURE_MR_SCORE_FIXED, DataRenderer.display(context, c)) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, ms.line(), ms.col(), ns.getLiteralPath(), false, I18nConstants.MEASURE_MR_SCORE_FIXED, DataRenderer.display(context, c)) && ok;
} }
} }
} }
@ -460,7 +460,7 @@ public class MeasureValidator extends BaseValidator {
private boolean banned(List<ValidationMessage> errors, NodeStack stack, Element e, String msgId, Object... params) { private boolean banned(List<ValidationMessage> errors, NodeStack stack, Element e, String msgId, Object... params) {
if (e != null) { if (e != null) {
NodeStack ns = stack.push(e, -1, e.getProperty().getDefinition(), e.getProperty().getDefinition()); NodeStack ns = stack.push(e, -1, e.getProperty().getDefinition(), e.getProperty().getDefinition());
rule(errors, IssueType.BUSINESSRULE, e.line(), e.col(), ns.getLiteralPath(), false, msgId, params); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, e.line(), e.col(), ns.getLiteralPath(), false, msgId, params);
return false; return false;
} else { } else {
return true; return true;
@ -476,10 +476,10 @@ public class MeasureValidator extends BaseValidator {
for (Element mrgp : plist) { for (Element mrgp : plist) {
NodeStack ns = stack.push(mrgp, i, mrgp.getProperty().getDefinition(), mrgp.getProperty().getDefinition()); NodeStack ns = stack.push(mrgp, i, mrgp.getProperty().getDefinition(), mrgp.getProperty().getDefinition());
CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrgp.getNamedChild("code")); CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrgp.getNamedChild("code"));
if (rule(errors, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), cc != null, I18nConstants.MEASURE_MR_GRP_POP_NO_CODE)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), cc != null, I18nConstants.MEASURE_MR_GRP_POP_NO_CODE)) {
MeasureGroupPopulationComponent mgp = getGroupPopForCode(cc, mg); MeasureGroupPopulationComponent mgp = getGroupPopForCode(cc, mg);
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mgp != null, I18nConstants.MEASURE_MR_GRP_POP_UNK_CODE)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mgp != null, I18nConstants.MEASURE_MR_GRP_POP_UNK_CODE)) {
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !pops.contains(mgp), I18nConstants.MEASURE_MR_GRP_POP_DUPL_CODE)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !pops.contains(mgp), I18nConstants.MEASURE_MR_GRP_POP_DUPL_CODE)) {
pops.add(mgp); pops.add(mgp);
ok = validateMeasureReportGroupPopulation(hostContext, m, mgp, errors, mrgp, ns, inProgress) && ok; ok = validateMeasureReportGroupPopulation(hostContext, m, mgp, errors, mrgp, ns, inProgress) && ok;
} else { } else {
@ -495,7 +495,7 @@ public class MeasureValidator extends BaseValidator {
} }
for (MeasureGroupPopulationComponent mgp : mg.getPopulation()) { for (MeasureGroupPopulationComponent mgp : mg.getPopulation()) {
if (!pops.contains(mgp) && !mgp.getCode().hasCoding("http://terminology.hl7.org/CodeSystem/measure-population", "measure-observation")) { if (!pops.contains(mgp) && !mgp.getCode().hasCoding("http://terminology.hl7.org/CodeSystem/measure-population", "measure-observation")) {
ok = rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), stack.getLiteralPath(), pops.contains(mg), I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, DataRenderer.display(context, mgp.getCode())) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), stack.getLiteralPath(), pops.contains(mg), I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, DataRenderer.display(context, mgp.getCode())) && ok;
} }
} }
return ok; return ok;
@ -507,13 +507,13 @@ public class MeasureValidator extends BaseValidator {
if ("subject-list".equals(m.reportType())) { if ("subject-list".equals(m.reportType())) {
try { try {
int c = Integer.parseInt(mrgp.getChildValue("count")); int c = Integer.parseInt(mrgp.getChildValue("count"));
ok = rule(errors, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), c == sr.size(), I18nConstants.MEASURE_MR_GRP_POP_COUNT_MISMATCH, c, sr.size()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), c == sr.size(), I18nConstants.MEASURE_MR_GRP_POP_COUNT_MISMATCH, c, sr.size()) && ok;
} catch (Exception e) { } catch (Exception e) {
// nothing; that'll be because count is not valid, and that's a different error or its missing and we don't care // nothing; that'll be because count is not valid, and that's a different error or its missing and we don't care
} }
} else { } else {
ok = rule(errors, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), sr.size() == 0, I18nConstants.MEASURE_MR_GRP_POP_NO_SUBJECTS) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), sr.size() == 0, I18nConstants.MEASURE_MR_GRP_POP_NO_SUBJECTS) && ok;
warning(errors, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), mrgp.hasChild("count"), I18nConstants.MEASURE_MR_GRP_POP_NO_COUNT); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgp.line(), mrgp.col(), ns.getLiteralPath(), mrgp.hasChild("count"), I18nConstants.MEASURE_MR_GRP_POP_NO_COUNT);
} }
return ok; return ok;
} }
@ -529,10 +529,10 @@ public class MeasureValidator extends BaseValidator {
for (Element mrgs : slist) { for (Element mrgs : slist) {
NodeStack ns = stack.push(mrgs, i, mrgs.getProperty().getDefinition(), mrgs.getProperty().getDefinition()); NodeStack ns = stack.push(mrgs, i, mrgs.getProperty().getDefinition(), mrgs.getProperty().getDefinition());
CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrgs.getNamedChild("code")); CodeableConcept cc = ObjectConverter.readAsCodeableConcept(mrgs.getNamedChild("code"));
if (rule(errors, IssueType.BUSINESSRULE, mrgs.line(), mrgs.col(), ns.getLiteralPath(), cc != null, I18nConstants.MEASURE_MR_GRP_POP_NO_CODE)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrgs.line(), mrgs.col(), ns.getLiteralPath(), cc != null, I18nConstants.MEASURE_MR_GRP_POP_NO_CODE)) {
MeasureGroupStratifierComponent mgs = getGroupStratifierForCode(cc, mg); MeasureGroupStratifierComponent mgs = getGroupStratifierForCode(cc, mg);
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mgs != null, I18nConstants.MEASURE_MR_GRP_POP_UNK_CODE)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), mgs != null, I18nConstants.MEASURE_MR_GRP_POP_UNK_CODE)) {
if (rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !strats.contains(mgs), I18nConstants.MEASURE_MR_GRP_POP_DUPL_CODE)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), ns.getLiteralPath(), !strats.contains(mgs), I18nConstants.MEASURE_MR_GRP_POP_DUPL_CODE)) {
strats.add(mgs); strats.add(mgs);
ok = validateMeasureReportGroupStratifier(hostContext, m, mgs, errors, mrgs, ns, inProgress) && ok; ok = validateMeasureReportGroupStratifier(hostContext, m, mgs, errors, mrgs, ns, inProgress) && ok;
} else { } else {
@ -548,7 +548,7 @@ public class MeasureValidator extends BaseValidator {
} }
for (MeasureGroupStratifierComponent mgs : mg.getStratifier()) { for (MeasureGroupStratifierComponent mgs : mg.getStratifier()) {
if (!strats.contains(mgs)) { if (!strats.contains(mgs)) {
ok = rule(errors, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), stack.getLiteralPath(), strats.contains(mg), I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, DataRenderer.display(context, mgs.getCode())) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, mrg.line(), mrg.col(), stack.getLiteralPath(), strats.contains(mg), I18nConstants.MEASURE_MR_GRP_MISSING_BY_CODE, DataRenderer.display(context, mgs.getCode())) && ok;
} }
} }
return true; return true;

View File

@ -142,14 +142,14 @@ public class QuestionnaireValidator extends BaseValidator {
List<Element> ewl = item.getChildren("enableWhen"); List<Element> ewl = item.getChildren("enableWhen");
for (Element ew : ewl) { for (Element ew : ewl) {
String ql = ew.getNamedChildValue("question"); String ql = ew.getNamedChildValue("question");
if (rule(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), ql != null, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_NOLINK)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, ns.getLiteralPath(), ql != null, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_NOLINK)) {
Element tgt = getQuestionById(item, ql); Element tgt = getQuestionById(item, ql);
if (rule(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), tgt == null, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_ISINNER)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, ns.getLiteralPath(), tgt == null, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_ISINNER)) {
tgt = getQuestionById(questionnaire, ql); tgt = getQuestionById(questionnaire, ql);
if (rule(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), tgt != null, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_NOTARGET, ql, item.getChildValue("linkId"))) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, ns.getLiteralPath(), tgt != null, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_NOTARGET, ql, item.getChildValue("linkId"))) {
if (rule(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), tgt != item, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_SELF)) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, ns.getLiteralPath(), tgt != item, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_SELF)) {
if (!isBefore(item, tgt, parents)) { if (!isBefore(item, tgt, parents)) {
warning(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_AFTER, ql); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, ns.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_Q_ENABLEWHEN_AFTER, ql);
} }
} else { } else {
ok = false; ok = false;
@ -245,10 +245,10 @@ public class QuestionnaireValidator extends BaseValidator {
} }
boolean qok; boolean qok;
if (questionnaireMode == QuestionnaireMode.REQUIRED) { if (questionnaireMode == QuestionnaireMode.REQUIRED) {
qok = rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE); qok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE);
ok = qok; ok = qok;
} else { } else {
qok = hint(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE); qok = hint(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), questionnaire != null, I18nConstants.QUESTIONNAIRE_QR_Q_NONE);
} }
if (qok) { if (qok) {
QuestionnaireWithContext qsrc = null; QuestionnaireWithContext qsrc = null;
@ -258,12 +258,12 @@ public class QuestionnaireValidator extends BaseValidator {
qsrc = QuestionnaireWithContext.fromQuestionnaire(context.fetchResource(Questionnaire.class, questionnaire)); qsrc = QuestionnaireWithContext.fromQuestionnaire(context.fetchResource(Questionnaire.class, questionnaire));
} }
if (questionnaireMode == QuestionnaireMode.REQUIRED) { if (questionnaireMode == QuestionnaireMode.REQUIRED) {
qok = rule(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire); qok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire);
ok = qok && ok; ok = qok && ok;
} else if (questionnaire.startsWith("http://example.org")) { } else if (questionnaire.startsWith("http://example.org")) {
qok = hint(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire); qok = hint(errors, NO_RULE_DATE, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire);
} else { } else {
qok = warning(errors, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire); qok = warning(errors, NO_RULE_DATE, IssueType.REQUIRED, q.line(), q.col(), stack.getLiteralPath(), qsrc != null, I18nConstants.QUESTIONNAIRE_QR_Q_NOTFOUND, questionnaire);
} }
if (qok) { if (qok) {
boolean inProgress = "in-progress".equals(element.getNamedChildValue("status")); boolean inProgress = "in-progress".equals(element.getNamedChildValue("status"));
@ -277,22 +277,22 @@ public class QuestionnaireValidator extends BaseValidator {
BooleanValue ok = new BooleanValue(true); BooleanValue ok = new BooleanValue(true);
String text = element.getNamedChildValue("text"); String text = element.getNamedChildValue("text");
ok.see(rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), Utilities.noString(text) || text.equals(qItem.getText()), I18nConstants.QUESTIONNAIRE_QR_ITEM_TEXT, qItem.getLinkId())); ok.see(rule(errors, NO_RULE_DATE, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), Utilities.noString(text) || text.equals(qItem.getText()), I18nConstants.QUESTIONNAIRE_QR_ITEM_TEXT, qItem.getLinkId()));
List<Element> answers = new ArrayList<Element>(); List<Element> answers = new ArrayList<Element>();
element.getNamedChildren("answer", answers); element.getNamedChildren("answer", answers);
if (inProgress) if (inProgress)
warning(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId()); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId());
else if (myEnableWhenEvaluator.isQuestionEnabled(hostContext, qItem, qstack, fpe)) { else if (myEnableWhenEvaluator.isQuestionEnabled(hostContext, qItem, qstack, fpe)) {
ok.see(rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId())); ok.see(rule(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), isAnswerRequirementFulfilled(qItem, answers), I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId()));
} else if (!answers.isEmpty()) { // items without answers should be allowed, but not items with answers to questions that are disabled } else if (!answers.isEmpty()) { // items without answers should be allowed, but not items with answers to questions that are disabled
// it appears that this is always a duplicate error - it will always already have been reported, so no need to report it again? // it appears that this is always a duplicate error - it will always already have been reported, so no need to report it again?
// GDG 2019-07-13 // GDG 2019-07-13
// rule(errors, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), !isAnswerRequirementFulfilled(qItem, answers), I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTENABLED, qItem.getLinkId()); // rule(errors, UNKNOWN_DATE_TIME, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), !isAnswerRequirementFulfilled(qItem, answers), I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTENABLED, qItem.getLinkId());
} }
if (answers.size() > 1) { if (answers.size() > 1) {
ok.see(rule(errors, IssueType.INVALID, answers.get(1).line(), answers.get(1).col(), stack.getLiteralPath(), qItem.getRepeats(), I18nConstants.QUESTIONNAIRE_QR_ITEM_ONLYONEA)); ok.see(rule(errors, NO_RULE_DATE, IssueType.INVALID, answers.get(1).line(), answers.get(1).col(), stack.getLiteralPath(), qItem.getRepeats(), I18nConstants.QUESTIONNAIRE_QR_ITEM_ONLYONEA));
} }
int i = 0; int i = 0;
@ -301,7 +301,7 @@ public class QuestionnaireValidator extends BaseValidator {
if (qItem.getType() != null) { if (qItem.getType() != null) {
switch (qItem.getType()) { switch (qItem.getType()) {
case GROUP: case GROUP:
ok.see(rule(errors, IssueType.STRUCTURE, answer.line(), answer.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_GROUP)); ok.see(rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, answer.line(), answer.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_GROUP));
break; break;
case DISPLAY: // nothing case DISPLAY: // nothing
break; break;
@ -381,15 +381,15 @@ public class QuestionnaireValidator extends BaseValidator {
i++; i++;
} }
if (qItem.getType() == null) { if (qItem.getType() == null) {
ok.see(fail(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTYPE, qItem.getLinkId())); ok.see(fail(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTYPE, qItem.getLinkId()));
} else if (qItem.getType() == QuestionnaireItemType.DISPLAY) { } else if (qItem.getType() == QuestionnaireItemType.DISPLAY) {
List<Element> items = new ArrayList<Element>(); List<Element> items = new ArrayList<Element>();
element.getNamedChildren("item", items); element.getNamedChildren("item", items);
ok.see(rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), items.isEmpty(), I18nConstants.QUESTIONNAIRE_QR_ITEM_DISPLAY, qItem.getLinkId())); ok.see(rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), items.isEmpty(), I18nConstants.QUESTIONNAIRE_QR_ITEM_DISPLAY, qItem.getLinkId()));
} else if (qItem.getType() != QuestionnaireItemType.GROUP) { } else if (qItem.getType() != QuestionnaireItemType.GROUP) {
List<Element> items = new ArrayList<Element>(); List<Element> items = new ArrayList<Element>();
element.getNamedChildren("item", items); element.getNamedChildren("item", items);
ok.see(rule(errors, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), items.isEmpty(), I18nConstants.QUESTIONNAIRE_QR_ITEM_GROUP_ANSWER, qItem.getLinkId())); ok.see(rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), items.isEmpty(), I18nConstants.QUESTIONNAIRE_QR_ITEM_GROUP_ANSWER, qItem.getLinkId()));
} else { } else {
ok.see(validateQuestionannaireResponseItems(hostContext, qsrc, qItem.getItem(), errors, element, stack, inProgress, questionnaireResponseRoot, qstack)); ok.see(validateQuestionannaireResponseItems(hostContext, qsrc, qItem.getItem(), errors, element, stack, inProgress, questionnaireResponseRoot, qstack));
} }
@ -403,7 +403,7 @@ public class QuestionnaireValidator extends BaseValidator {
private boolean validateQuestionnaireResponseItem(ValidatorHostContext hostcontext, QuestionnaireWithContext qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, List<ElementWithIndex> elements, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) { private boolean validateQuestionnaireResponseItem(ValidatorHostContext hostcontext, QuestionnaireWithContext qsrc, QuestionnaireItemComponent qItem, List<ValidationMessage> errors, List<ElementWithIndex> elements, NodeStack stack, boolean inProgress, Element questionnaireResponseRoot, QStack qstack) {
boolean ok = true; boolean ok = true;
if (elements.size() > 1) { if (elements.size() > 1) {
ok = rulePlural(errors, IssueType.INVALID, elements.get(1).getElement().line(), elements.get(1).getElement().col(), stack.getLiteralPath(), qItem.getRepeats(), elements.size(), I18nConstants.QUESTIONNAIRE_QR_ITEM_ONLYONEI, qItem.getLinkId()) && ok; ok = rulePlural(errors, NO_RULE_DATE, IssueType.INVALID, elements.get(1).getElement().line(), elements.get(1).getElement().col(), stack.getLiteralPath(), qItem.getRepeats(), elements.size(), I18nConstants.QUESTIONNAIRE_QR_ITEM_ONLYONEI, qItem.getLinkId()) && ok;
} }
for (ElementWithIndex element : elements) { for (ElementWithIndex element : elements) {
NodeStack ns = stack.push(element.getElement(), element.getIndex(), null, null); NodeStack ns = stack.push(element.getElement(), element.getIndex(), null, null);
@ -430,18 +430,18 @@ public class QuestionnaireValidator extends BaseValidator {
int counter = 0; int counter = 0;
for (Element item : items) { for (Element item : items) {
String linkId = item.getNamedChildValue("linkId"); String linkId = item.getNamedChildValue("linkId");
if (rule(errors, IssueType.REQUIRED, item.line(), item.col(), stack.getLiteralPath(), !Utilities.noString(linkId), I18nConstants.QUESTIONNAIRE_QR_ITEM_NOLINKID)) { if (rule(errors, NO_RULE_DATE, IssueType.REQUIRED, item.line(), item.col(), stack.getLiteralPath(), !Utilities.noString(linkId), I18nConstants.QUESTIONNAIRE_QR_ITEM_NOLINKID)) {
int index = getLinkIdIndex(qItems, linkId); int index = getLinkIdIndex(qItems, linkId);
if (index == -1) { if (index == -1) {
QuestionnaireItemComponent qItem = findQuestionnaireItem(qsrc, linkId); QuestionnaireItemComponent qItem = findQuestionnaireItem(qsrc, linkId);
if (qItem != null) { if (qItem != null) {
ok = rule(errors, IssueType.STRUCTURE, item.line(), item.col(), stack.getLiteralPath(), index > -1, misplacedItemError(qItem)) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, item.line(), item.col(), stack.getLiteralPath(), index > -1, misplacedItemError(qItem)) && ok;
NodeStack ns = stack.push(item, counter, null, null); NodeStack ns = stack.push(item, counter, null, null);
ok = validateQuestionnaireResponseItem(hostContext, qsrc, qItem, errors, item, ns, inProgress, questionnaireResponseRoot, qstack.push(qItem, item)) && ok; ok = validateQuestionnaireResponseItem(hostContext, qsrc, qItem, errors, item, ns, inProgress, questionnaireResponseRoot, qstack.push(qItem, item)) && ok;
} else } else
ok = rule(errors, IssueType.NOTFOUND, item.line(), item.col(), stack.getLiteralPath(), index > -1, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTFOUND, linkId) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, item.line(), item.col(), stack.getLiteralPath(), index > -1, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTFOUND, linkId) && ok;
} else { } else {
ok = rule(errors, IssueType.STRUCTURE, item.line(), item.col(), stack.getLiteralPath(), index >= lastIndex, I18nConstants.QUESTIONNAIRE_QR_ITEM_ORDER) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, item.line(), item.col(), stack.getLiteralPath(), index >= lastIndex, I18nConstants.QUESTIONNAIRE_QR_ITEM_ORDER) && ok;
lastIndex = index; lastIndex = index;
// If an item has a child called "linkId" but no child called "answer", // If an item has a child called "linkId" but no child called "answer",
@ -472,7 +472,7 @@ public class QuestionnaireValidator extends BaseValidator {
if (!enabled) { if (!enabled) {
for (ElementWithIndex e : mapItem) { for (ElementWithIndex e : mapItem) {
NodeStack ns = stack.push(e.getElement(), e.getElement().getIndex(), e.getElement().getProperty().getDefinition(), e.getElement().getProperty().getDefinition()); NodeStack ns = stack.push(e.getElement(), e.getElement().getIndex(), e.getElement().getProperty().getDefinition(), e.getElement().getProperty().getDefinition());
ok = rule(errors, IssueType.INVALID, e.getElement().line(), e.getElement().col(), ns.getLiteralPath(), enabled, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTENABLED2, qItem.getLinkId()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.INVALID, e.getElement().line(), e.getElement().col(), ns.getLiteralPath(), enabled, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTENABLED2, qItem.getLinkId()) && ok;
} }
} }
@ -485,9 +485,9 @@ public class QuestionnaireValidator extends BaseValidator {
if (enabled && qItem.getRequired()) { if (enabled && qItem.getRequired()) {
String message = context.formatMessage(I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId()); String message = context.formatMessage(I18nConstants.QUESTIONNAIRE_QR_ITEM_MISSING, qItem.getLinkId());
if (inProgress) { if (inProgress) {
warning(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), false, message); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), false, message);
} else { } else {
ok = rule(errors, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), false, message) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, element.line(), element.col(), stack.getLiteralPath(), false, message) && ok;
} }
} }
@ -520,7 +520,7 @@ public class QuestionnaireValidator extends BaseValidator {
return (s); return (s);
} }
ok.see(rulePlural(errors, IssueType.STRUCTURE, values.get(0).line(), values.get(0).col(), ns.getLiteralPath(), false, types.length, I18nConstants.QUESTIONNAIRE_QR_ITEM_WRONGTYPE, l.toString())); ok.see(rulePlural(errors, NO_RULE_DATE, IssueType.STRUCTURE, values.get(0).line(), values.get(0).col(), ns.getLiteralPath(), false, types.length, I18nConstants.QUESTIONNAIRE_QR_ITEM_WRONGTYPE, l.toString()));
} }
return null; return null;
} }
@ -548,7 +548,7 @@ public class QuestionnaireValidator extends BaseValidator {
} else { } else {
vs = resolveBindingReference(qSrc.q(), ref, qSrc.q().getUrl()); vs = resolveBindingReference(qSrc.q(), ref, qSrc.q().getUrl());
} }
if (warning(errors, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), vs != null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND, describeReference(ref))) { if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), vs != null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND, describeReference(ref))) {
try { try {
Coding c = ObjectConverter.readAsCoding(value); Coding c = ObjectConverter.readAsCoding(value);
if (isBlank(c.getCode()) && isBlank(c.getSystem()) && isNotBlank(c.getDisplay())) { if (isBlank(c.getCode()) && isBlank(c.getSystem()) && isNotBlank(c.getDisplay())) {
@ -562,14 +562,14 @@ public class QuestionnaireValidator extends BaseValidator {
ValidationResult res = context.validateCode(new ValidationOptions(stack.getWorkingLang()), c, vs, vc); ValidationResult res = context.validateCode(new ValidationOptions(stack.getWorkingLang()), c, vs, vc);
timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'"); timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'");
if (!res.isOk()) { if (!res.isOk()) {
ok = txRule(errors, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION, c.getSystem(), c.getCode()) && ok; ok = txRule(errors, NO_RULE_DATE, res.getTxLink(), IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_BADOPTION, c.getSystem(), c.getCode()) && ok;
} else if (res.getSeverity() != null) { } else if (res.getSeverity() != null) {
super.addValidationMessage(errors, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity(), Source.TerminologyEngine, null); super.addValidationMessage(errors, NO_RULE_DATE, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity(), Source.TerminologyEngine, null);
} else if (res.getMessage() != null) { } else if (res.getMessage() != null) {
super.addValidationMessage(errors, IssueType.INFORMATIONAL, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity() == null ? IssueSeverity.INFORMATION : res.getSeverity(), Source.TerminologyEngine, null); super.addValidationMessage(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, value.line(), value.col(), stack.getLiteralPath(), res.getMessage(), res.getSeverity() == null ? IssueSeverity.INFORMATION : res.getSeverity(), Source.TerminologyEngine, null);
} }
} catch (Exception e) { } catch (Exception e) {
warning(errors, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_CODING, e.getMessage()); warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_CODING, e.getMessage());
} }
} }
return ok; return ok;
@ -594,7 +594,7 @@ public class QuestionnaireValidator extends BaseValidator {
else if (qItem.hasAnswerValueSet()) else if (qItem.hasAnswerValueSet())
return validateAnswerCode(errors, v, stack, qSrc, qItem.getAnswerValueSet(), theOpenChoice); return validateAnswerCode(errors, v, stack, qSrc, qItem.getAnswerValueSet(), theOpenChoice);
else else
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONS); hint(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONS);
return true; return true;
} }
@ -625,7 +625,7 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
if (list.isEmpty() && !openChoice) { if (list.isEmpty() && !openChoice) {
ok = rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSINTEGER) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSINTEGER) && ok;
} else { } else {
boolean found = false; boolean found = false;
for (IntegerType item : list) { for (IntegerType item : list) {
@ -635,11 +635,11 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
if (!found) { if (!found) {
ok = rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOINTEGER, v.primitiveValue()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOINTEGER, v.primitiveValue()) && ok;
} }
} }
} else { } else {
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_INTNOOPTIONS); hint(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_INTNOOPTIONS);
} }
return ok; return ok;
} }
@ -658,7 +658,7 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
if (list.isEmpty() && !openChoice) { if (list.isEmpty() && !openChoice) {
ok = rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSDATE) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSDATE) && ok;
} else { } else {
boolean found = false; boolean found = false;
for (DateType item : list) { for (DateType item : list) {
@ -668,11 +668,11 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
if (!found) { if (!found) {
ok = rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NODATE, v.primitiveValue()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NODATE, v.primitiveValue()) && ok;
} }
} }
} else { } else {
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_DATENOOPTIONS); hint(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_DATENOOPTIONS);
} }
return ok; return ok;
} }
@ -691,7 +691,7 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
if (list.isEmpty() && !openChoice) { if (list.isEmpty() && !openChoice) {
ok = rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSTIME) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSTIME) && ok;
} else { } else {
boolean found = false; boolean found = false;
for (TimeType item : list) { for (TimeType item : list) {
@ -701,11 +701,11 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
if (!found) { if (!found) {
ok = rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTIME, v.primitiveValue()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOTIME, v.primitiveValue()) && ok;
} }
} }
} else { } else {
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_TIMENOOPTIONS); hint(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_TIMENOOPTIONS);
} }
return ok; return ok;
} }
@ -727,7 +727,7 @@ public class QuestionnaireValidator extends BaseValidator {
} }
if (!openChoice) { if (!openChoice) {
if (list.isEmpty()) { if (list.isEmpty()) {
ok = rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSSTRING) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSSTRING) && ok;
} else { } else {
boolean found = false; boolean found = false;
for (StringType item : list) { for (StringType item : list) {
@ -737,12 +737,12 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
if (!found) { if (!found) {
ok = rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOSTRING, v.primitiveValue()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOSTRING, v.primitiveValue()) && ok;
} }
} }
} }
} else { } else {
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_STRINGNOOPTIONS); hint(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_STRINGNOOPTIONS);
} }
return ok; return ok;
} }
@ -766,7 +766,7 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
if (list.isEmpty() && !openChoice) { if (list.isEmpty() && !openChoice) {
ok = rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSCODING) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOOPTIONSCODING) && ok;
} else { } else {
boolean found = false; boolean found = false;
for (Coding item : list) { for (Coding item : list) {
@ -776,11 +776,11 @@ public class QuestionnaireValidator extends BaseValidator {
} }
} }
if (!found) { if (!found) {
ok = rule(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOCODING, system, code) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), found, I18nConstants.QUESTIONNAIRE_QR_ITEM_NOCODING, system, code) && ok;
} }
} }
} else { } else {
hint(errors, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_CODINGNOOPTIONS); hint(errors, NO_RULE_DATE, IssueType.STRUCTURE, v.line(), v.col(), stack.getLiteralPath(), false, I18nConstants.QUESTIONNAIRE_QR_ITEM_CODINGNOOPTIONS);
} }
return ok; return ok;
} }

View File

@ -51,13 +51,13 @@ public class SearchParameterValidator extends BaseValidator {
if (!Utilities.noString(master)) { if (!Utilities.noString(master)) {
SearchParameter sp = context.fetchResource(SearchParameter.class, master); SearchParameter sp = context.fetchResource(SearchParameter.class, master);
if (warning(errors, IssueType.BUSINESSRULE,stack.getLiteralPath(), sp != null, I18nConstants.SEARCHPARAMETER_NOTFOUND, master)) { if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE,stack.getLiteralPath(), sp != null, I18nConstants.SEARCHPARAMETER_NOTFOUND, master)) {
// base must be in the master list of base // base must be in the master list of base
List<Element> bl = cs.getChildren("base"); List<Element> bl = cs.getChildren("base");
for (Element b : bl) { for (Element b : bl) {
ok = rule(errors, IssueType.BUSINESSRULE,stack.getLiteralPath(), sp.hasBase(b.primitiveValue()) || sp.hasBase("Resource"), I18nConstants.SEARCHPARAMETER_BASE_WRONG, master, b.primitiveValue()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE,stack.getLiteralPath(), sp.hasBase(b.primitiveValue()) || sp.hasBase("Resource"), I18nConstants.SEARCHPARAMETER_BASE_WRONG, master, b.primitiveValue()) && ok;
} }
ok = rule(errors, IssueType.BUSINESSRULE,stack.getLiteralPath(), !cs.hasChild("type") || sp.getType().toCode().equals(cs.getNamedChildValue("type")), I18nConstants.SEARCHPARAMETER_TYPE_WRONG, master, sp.getType().toCode(), cs.getNamedChildValue("type")) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE,stack.getLiteralPath(), !cs.hasChild("type") || sp.getType().toCode().equals(cs.getNamedChildValue("type")), I18nConstants.SEARCHPARAMETER_TYPE_WRONG, master, sp.getType().toCode(), cs.getNamedChildValue("type")) && ok;
if (sp.hasExpression() && cs.hasChild("expression") && !sp.getExpression().equals(cs.getNamedChildValue("expression"))) { if (sp.hasExpression() && cs.hasChild("expression") && !sp.getExpression().equals(cs.getNamedChildValue("expression"))) {
List<String> bases = new ArrayList<>(); List<String> bases = new ArrayList<>();
for (Element b : cs.getChildren("base")) { for (Element b : cs.getChildren("base")) {
@ -65,7 +65,7 @@ public class SearchParameterValidator extends BaseValidator {
} }
String expThis = canonicalise(cs.getNamedChildValue("expression"), bases); String expThis = canonicalise(cs.getNamedChildValue("expression"), bases);
String expOther = canonicalise(sp.getExpression(), bases); String expOther = canonicalise(sp.getExpression(), bases);
warning(errors, IssueType.BUSINESSRULE,stack.getLiteralPath(), expThis.equals(expOther), I18nConstants.SEARCHPARAMETER_EXP_WRONG, master, sp.getExpression(), cs.getNamedChildValue("expression")); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE,stack.getLiteralPath(), expThis.equals(expOther), I18nConstants.SEARCHPARAMETER_EXP_WRONG, master, sp.getExpression(), cs.getNamedChildValue("expression"));
} }
// todo: check compositions // todo: check compositions
} }

View File

@ -76,12 +76,12 @@ public class StructureDefinitionValidator extends BaseValidator {
sd.setSnapshot(null); sd.setSnapshot(null);
typeName = sd.getTypeName(); typeName = sd.getTypeName();
StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
if (warning(errors, IssueType.NOTFOUND, stack.getLiteralPath(), base != null, I18nConstants.UNABLE_TO_FIND_BASE__FOR_, sd.getBaseDefinition(), "StructureDefinition, so can't check the differential")) { if (warning(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), base != null, I18nConstants.UNABLE_TO_FIND_BASE__FOR_, sd.getBaseDefinition(), "StructureDefinition, so can't check the differential")) {
if (rule(errors, IssueType.NOTFOUND, stack.getLiteralPath(), sd.hasDerivation(), I18nConstants.SD_MUST_HAVE_DERIVATION, sd.getUrl())) { if (rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), sd.hasDerivation(), I18nConstants.SD_MUST_HAVE_DERIVATION, sd.getUrl())) {
boolean bok = base.getAbstract() || sd.hasKind() && sd.getKind() == base.getKind(); boolean bok = base.getAbstract() || sd.hasKind() && sd.getKind() == base.getKind();
rule(errors, IssueType.NOTFOUND, stack.getLiteralPath(), bok, I18nConstants.SD_CONSTRAINED_KIND_NO_MATCH, sd.getKind().toCode(), base.getKind().toCode(), base.getType(), base.getUrl()); rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), bok, I18nConstants.SD_CONSTRAINED_KIND_NO_MATCH, sd.getKind().toCode(), base.getKind().toCode(), base.getType(), base.getUrl());
if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT) { if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT) {
rule(errors, IssueType.NOTFOUND, stack.getLiteralPath(), sd.hasType() && sd.getType().equals(base.getType()), I18nConstants.SD_CONSTRAINED_TYPE_NO_MATCH, sd.getType(), base.getType()); rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), sd.hasType() && sd.getType().equals(base.getType()), I18nConstants.SD_CONSTRAINED_TYPE_NO_MATCH, sd.getType(), base.getType());
List<ValidationMessage> msgs = new ArrayList<>(); List<ValidationMessage> msgs = new ArrayList<>();
ProfileUtilities pu = new ProfileUtilities(context, msgs, null); ProfileUtilities pu = new ProfileUtilities(context, msgs, null);
pu.setXver(xverManager); pu.setXver(xverManager);
@ -103,21 +103,21 @@ public class StructureDefinitionValidator extends BaseValidator {
if (!snapshot.isEmpty() && wantCheckSnapshotUnchanged) { if (!snapshot.isEmpty() && wantCheckSnapshotUnchanged) {
int was = snapshot.size(); int was = snapshot.size();
int is = sd.getSnapshot().getElement().size(); int is = sd.getSnapshot().getElement().size();
ok = rule(errors, IssueType.NOTFOUND, stack.getLiteralPath(), was == is, I18nConstants.SNAPSHOT_EXISTING_PROBLEM, was, is) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), was == is, I18nConstants.SNAPSHOT_EXISTING_PROBLEM, was, is) && ok;
} }
} else { } else {
rule(errors, IssueType.NOTFOUND, stack.getLiteralPath(), sd.hasType() && !sd.getType().equals(base.getType()), I18nConstants.SD_SPECIALIZED_TYPE_MATCHES, sd.getType(), base.getType()); rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), sd.hasType() && !sd.getType().equals(base.getType()), I18nConstants.SD_SPECIALIZED_TYPE_MATCHES, sd.getType(), base.getType());
} }
} else { } else {
ok = false; ok = false;
} }
if ("constraint".equals(src.getChildValue("derivation"))) { if ("constraint".equals(src.getChildValue("derivation"))) {
ok = rule(errors, IssueType.NOTFOUND, stack.getLiteralPath(), base.getKindElement().primitiveValue().equals(src.getChildValue("kind")), ok = rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), base.getKindElement().primitiveValue().equals(src.getChildValue("kind")),
I18nConstants.SD_DERIVATION_KIND_MISMATCH, base.getKindElement().primitiveValue(), src.getChildValue("kind")) && ok; I18nConstants.SD_DERIVATION_KIND_MISMATCH, base.getKindElement().primitiveValue(), src.getChildValue("kind")) && ok;
} }
} }
} catch (FHIRException | IOException e) { } catch (FHIRException | IOException e) {
rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage()); rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage());
ok = false; ok = false;
} }
List<Element> differentials = src.getChildrenByName("differential"); List<Element> differentials = src.getChildrenByName("differential");
@ -146,7 +146,7 @@ public class StructureDefinitionValidator extends BaseValidator {
boolean ok = true; boolean ok = true;
boolean typeMustSupport = false; boolean typeMustSupport = false;
String path = element.getNamedChildValue("path"); String path = element.getNamedChildValue("path");
rule(errors, IssueType.NOTFOUND, stack.getLiteralPath(), typeName == null || path == null || path.equals(typeName) || path.startsWith(typeName+"."), I18nConstants.SD_PATH_TYPE_MISMATCH, typeName, path); rule(errors, NO_RULE_DATE, IssueType.NOTFOUND, stack.getLiteralPath(), typeName == null || path == null || path.equals(typeName) || path.startsWith(typeName+"."), I18nConstants.SD_PATH_TYPE_MISMATCH, typeName, path);
List<Element> types = element.getChildrenByName("type"); List<Element> types = element.getChildrenByName("type");
Set<String> typeCodes = new HashSet<>(); Set<String> typeCodes = new HashSet<>();
Set<String> characteristics = new HashSet<>(); Set<String> characteristics = new HashSet<>();
@ -178,7 +178,7 @@ public class StructureDefinitionValidator extends BaseValidator {
} }
characteristics.addAll(tcharacteristics); characteristics.addAll(tcharacteristics);
if (type.hasChildren("targetProfile")) { if (type.hasChildren("targetProfile")) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), tcharacteristics.contains("has-target") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "targetProfile", tc) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), tcharacteristics.contains("has-target") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "targetProfile", tc) && ok;
} }
// check the stated profile - must be a constraint on the type // check the stated profile - must be a constraint on the type
if (snapshot || sd != null) { if (snapshot || sd != null) {
@ -187,68 +187,68 @@ public class StructureDefinitionValidator extends BaseValidator {
} }
if (typeMustSupport) { if (typeMustSupport) {
if (snapshot) { if (snapshot) {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), "true".equals(element.getChildValue("mustSupport")), I18nConstants.SD_NESTED_MUST_SUPPORT_SNAPSHOT, path) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), "true".equals(element.getChildValue("mustSupport")), I18nConstants.SD_NESTED_MUST_SUPPORT_SNAPSHOT, path) && ok;
} else { } else {
hint(errors, IssueType.EXCEPTION, stack.getLiteralPath(), hasSnapshot || "true".equals(element.getChildValue("mustSupport")), I18nConstants.SD_NESTED_MUST_SUPPORT_DIFF, path); hint(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), hasSnapshot || "true".equals(element.getChildValue("mustSupport")), I18nConstants.SD_NESTED_MUST_SUPPORT_DIFF, path);
} }
} }
if (element.hasChild("binding")) { if (element.hasChild("binding")) {
if (!typeCodes.isEmpty()) { if (!typeCodes.isEmpty()) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("can-bind") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "Binding", typeCodes) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("can-bind") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "Binding", typeCodes) && ok;
} }
Element binding = element.getNamedChild("binding"); Element binding = element.getNamedChild("binding");
ok = validateBinding(errors, binding, stack.push(binding, -1, null, null), typeCodes, snapshot, path) && ok; ok = validateBinding(errors, binding, stack.push(binding, -1, null, null), typeCodes, snapshot, path) && ok;
} else { } else {
// this is a good idea but there's plenty of cases where the rule isn't met; maybe one day it's worth investing the time to exclude these cases and bring this rule back // this is a good idea but there's plenty of cases where the rule isn't met; maybe one day it's worth investing the time to exclude these cases and bring this rule back
// String bt = boundType(typeCodes); // String bt = boundType(typeCodes);
// hint(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || bt == null, I18nConstants.SD_ED_SHOULD_BIND, element.getNamedChildValue("path"), bt); // hint(errors, UNKNOWN_DATE_TIME, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || bt == null, I18nConstants.SD_ED_SHOULD_BIND, element.getNamedChildValue("path"), bt);
} }
if (!typeCodes.isEmpty()) { if (!typeCodes.isEmpty()) {
if (element.hasChild("maxLength")) { if (element.hasChild("maxLength")) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("has-length") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "MaxLength", typeCodes) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("has-length") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "MaxLength", typeCodes) && ok;
} }
if (element.hasExtension(ToolingExtensions.EXT_MIN_LENGTH)) { if (element.hasExtension(ToolingExtensions.EXT_MIN_LENGTH)) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("has-length") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "MinLength Extension", typeCodes) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("has-length") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "MinLength Extension", typeCodes) && ok;
} }
if (element.hasChild("minValue")) { if (element.hasChild("minValue")) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("has-range") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "MinValue", typeCodes) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("has-range") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "MinValue", typeCodes) && ok;
} }
if (element.hasChild("maxValue")) { if (element.hasChild("maxValue")) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("has-range") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "MaxValue", typeCodes) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("has-range") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "MaxValue", typeCodes) && ok;
} }
if (element.hasExtension(ToolingExtensions.EXT_MAX_DECIMALS)) { if (element.hasExtension(ToolingExtensions.EXT_MAX_DECIMALS)) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("is-continuous") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "Max Decimal Places Extension", typeCodes) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("is-continuous") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "Max Decimal Places Extension", typeCodes) && ok;
} }
if (element.hasExtension(ToolingExtensions.EXT_MAX_SIZE)) { if (element.hasExtension(ToolingExtensions.EXT_MAX_SIZE)) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("has-size") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "Max Size", typeCodes) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("has-size") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "Max Size", typeCodes) && ok;
} }
} }
// in a snapshot, we validate that fixedValue, pattern, and defaultValue, if present, are all of the right type // in a snapshot, we validate that fixedValue, pattern, and defaultValue, if present, are all of the right type
if (snapshot && (element.getIdBase() != null) && (element.getIdBase().contains("."))) { if (snapshot && (element.getIdBase() != null) && (element.getIdBase().contains("."))) {
if (rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), !typeCodes.isEmpty() || element.hasChild("contentReference"), I18nConstants.SD_NO_TYPES_OR_CONTENTREF, element.getIdBase())) { if (rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), !typeCodes.isEmpty() || element.hasChild("contentReference"), I18nConstants.SD_NO_TYPES_OR_CONTENTREF, element.getIdBase())) {
// if we see fixed[x] or pattern[x] applied to a repeating element, we'll give the user a hint // if we see fixed[x] or pattern[x] applied to a repeating element, we'll give the user a hint
boolean repeating = !Utilities.existsInList(element.getChildValue("max"), "0", "1"); boolean repeating = !Utilities.existsInList(element.getChildValue("max"), "0", "1");
Element v = element.getNamedChild("defaultValue"); Element v = element.getNamedChild("defaultValue");
if (v != null) { if (v != null) {
ok = rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "defaultValue", v.fhirType(), typeCodes) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "defaultValue", v.fhirType(), typeCodes) && ok;
} }
v = element.getNamedChild("fixed"); v = element.getNamedChild("fixed");
if (v != null) { if (v != null) {
ok = rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "fixed", v.fhirType(), typeCodes) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "fixed", v.fhirType(), typeCodes) && ok;
hint(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_HINT, element.getIdBase(), "fixed"); hint(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_HINT, element.getIdBase(), "fixed");
if (isPrimitiveType(v.fhirType())) { if (isPrimitiveType(v.fhirType())) {
warning(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_WARNING_DOTNET, element.getIdBase(), "fixed"); warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_WARNING_DOTNET, element.getIdBase(), "fixed");
} else { } else {
warning(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), false, I18nConstants.SD_VALUE_COMPLEX_FIXED, v.fhirType()); warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), false, I18nConstants.SD_VALUE_COMPLEX_FIXED, v.fhirType());
} }
} }
v = element.getNamedChild("pattern"); v = element.getNamedChild("pattern");
if (v != null) { if (v != null) {
ok = rule(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "pattern", v.fhirType(), typeCodes) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), typeCodes.contains(v.fhirType()), I18nConstants.SD_VALUE_TYPE_IILEGAL, element.getIdBase(), "pattern", v.fhirType(), typeCodes) && ok;
hint(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_HINT, element.getIdBase(), "pattern"); hint(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_HINT, element.getIdBase(), "pattern");
if (isPrimitiveType(v.fhirType())) { if (isPrimitiveType(v.fhirType())) {
warning(errors, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_WARNING_DOTNET, element.getIdBase(), "pattern"); warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.push(v, -1, null, null).getLiteralPath(), !repeating, I18nConstants.SD_VALUE_TYPE_REPEAT_WARNING_DOTNET, element.getIdBase(), "pattern");
} }
} }
} }
@ -385,24 +385,24 @@ public class StructureDefinitionValidator extends BaseValidator {
private boolean validateBinding(List<ValidationMessage> errors, Element binding, NodeStack stack, Set<String> typeCodes, boolean snapshot, String path) { private boolean validateBinding(List<ValidationMessage> errors, Element binding, NodeStack stack, Set<String> typeCodes, boolean snapshot, String path) {
boolean ok = true; boolean ok = true;
if (bindableType(typeCodes) == null) { if (bindableType(typeCodes) == null) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot, I18nConstants.SD_ED_BIND_NO_BINDABLE, path, typeCodes.toString()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot, I18nConstants.SD_ED_BIND_NO_BINDABLE, path, typeCodes.toString()) && ok;
} }
if (!snapshot) { if (!snapshot) {
Set<String> bindables = getListofBindableTypes(typeCodes); Set<String> bindables = getListofBindableTypes(typeCodes);
hint(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), bindables.size() <= 1, I18nConstants.SD_ED_BIND_MULTIPLE_TYPES, path, typeCodes.toString()); hint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), bindables.size() <= 1, I18nConstants.SD_ED_BIND_MULTIPLE_TYPES, path, typeCodes.toString());
} }
if (binding.hasChild("valueSet")) { if (binding.hasChild("valueSet")) {
Element valueSet = binding.getNamedChild("valueSet"); Element valueSet = binding.getNamedChild("valueSet");
String ref = valueSet.hasPrimitiveValue() ? valueSet.primitiveValue() : valueSet.getNamedChildValue("reference"); String ref = valueSet.hasPrimitiveValue() ? valueSet.primitiveValue() : valueSet.getNamedChildValue("reference");
if (warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || ref != null, I18nConstants.SD_ED_SHOULD_BIND_WITH_VS, path)) { if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || ref != null, I18nConstants.SD_ED_SHOULD_BIND_WITH_VS, path)) {
Resource vs = context.fetchResource(Resource.class, ref); Resource vs = context.fetchResource(Resource.class, ref);
// just because we can't resolve it directly doesn't mean that terminology server can't. Check with it // just because we can't resolve it directly doesn't mean that terminology server can't. Check with it
if (warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null || serverSupportsValueSet(ref), I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) { if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null || serverSupportsValueSet(ref), I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) {
if (vs != null) { if (vs != null) {
ok = rule(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType()) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType()) && ok;
} }
} }
} }
@ -456,31 +456,31 @@ public class StructureDefinitionValidator extends BaseValidator {
String p = profile.primitiveValue(); String p = profile.primitiveValue();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p); StructureDefinition sd = context.fetchResource(StructureDefinition.class, p);
if (code.equals("Reference")) { if (code.equals("Reference")) {
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) { if (warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
StructureDefinition t = determineBaseType(sd); StructureDefinition t = determineBaseType(sd);
if (t == null) { if (t == null) {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok;
} else { } else {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd.getKind() == StructureDefinitionKind.RESOURCE, I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), sd.getKind() == StructureDefinitionKind.RESOURCE, I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path) && ok;
} }
} }
} else { } else {
if (sd == null ) { if (sd == null ) {
sd = getXverExt(errors, stack.getLiteralPath(), profile, p); sd = getXverExt(errors, stack.getLiteralPath(), profile, p);
} }
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) { if (warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
StructureDefinition t = determineBaseType(sd); StructureDefinition t = determineBaseType(sd);
if (t == null) { if (t == null) {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok;
} else { } else {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), isInstanceOf(t, code), I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), isInstanceOf(t, code), I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path) && ok;
if (t.getType().equals("Extension")) { if (t.getType().equals("Extension")) {
boolean isModifierDefinition = checkIsModifierExtension(sd); boolean isModifierDefinition = checkIsModifierExtension(sd);
boolean isModifierContext = path.endsWith(".modifierExtension"); boolean isModifierContext = path.endsWith(".modifierExtension");
if (isModifierDefinition) { if (isModifierDefinition) {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), isModifierContext, I18nConstants.SD_ED_TYPE_PROFILE_NOT_MODIFIER, p, t, code, path) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), isModifierContext, I18nConstants.SD_ED_TYPE_PROFILE_NOT_MODIFIER, p, t, code, path) && ok;
} else { } else {
ok =rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), !isModifierContext, I18nConstants.SD_ED_TYPE_PROFILE_IS_MODIFIER, p, t, code, path) && ok; ok =rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), !isModifierContext, I18nConstants.SD_ED_TYPE_PROFILE_IS_MODIFIER, p, t, code, path) && ok;
} }
} }
} }
@ -510,20 +510,20 @@ public class StructureDefinitionValidator extends BaseValidator {
if (sd == null ) { if (sd == null ) {
sd = getXverExt(errors, stack.getLiteralPath(), profile, p); sd = getXverExt(errors, stack.getLiteralPath(), profile, p);
} }
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) { if (warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
StructureDefinition t = determineBaseType(sd); StructureDefinition t = determineBaseType(sd);
if (t == null) { if (t == null) {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok;
} else if (!isInstanceOf(t, code)) { } else if (!isInstanceOf(t, code)) {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_WRONG, p, t, code, path) && ok;
} else { } else {
if (t.getType().equals("Extension")) { if (t.getType().equals("Extension")) {
boolean isModifierDefinition = checkIsModifierExtension(sd); boolean isModifierDefinition = checkIsModifierExtension(sd);
boolean isModifierContext = path.endsWith(".modifierExtension"); boolean isModifierContext = path.endsWith(".modifierExtension");
if (isModifierDefinition) { if (isModifierDefinition) {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), isModifierContext, I18nConstants.SD_ED_TYPE_PROFILE_NOT_MODIFIER, p, t, code, path) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), isModifierContext, I18nConstants.SD_ED_TYPE_PROFILE_NOT_MODIFIER, p, t, code, path) && ok;
} else { } else {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), !isModifierContext, I18nConstants.SD_ED_TYPE_PROFILE_IS_MODIFIER, p, t, code, path) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), !isModifierContext, I18nConstants.SD_ED_TYPE_PROFILE_IS_MODIFIER, p, t, code, path) && ok;
} }
} }
} }
@ -540,27 +540,27 @@ public class StructureDefinitionValidator extends BaseValidator {
String p = profile.primitiveValue(); String p = profile.primitiveValue();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p); StructureDefinition sd = context.fetchResource(StructureDefinition.class, p);
if (code.equals("Reference") || code.equals("CodeableReference")) { if (code.equals("Reference") || code.equals("CodeableReference")) {
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) { if (warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
StructureDefinition t = determineBaseType(sd); StructureDefinition t = determineBaseType(sd);
if (t == null) { if (t == null) {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok;
} else { } else {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd.getKind() == StructureDefinitionKind.RESOURCE, I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Resource") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), sd.getKind() == StructureDefinitionKind.RESOURCE, I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Resource") && ok;
} }
} }
} else if (code.equals("canonical")) { } else if (code.equals("canonical")) {
if (warning(errors, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) { if (warning(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), sd != null, I18nConstants.SD_ED_TYPE_PROFILE_UNKNOWN, p)) {
StructureDefinition t = determineBaseType(sd); StructureDefinition t = determineBaseType(sd);
if (t == null) { if (t == null) {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_PROFILE_NOTYPE, p) && ok;
} else if (!VersionUtilities.isR5Ver(context.getVersion())) { } else if (!VersionUtilities.isR5Ver(context.getVersion())) {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(t.getType()) || "Resource".equals(t.getType()), I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Canonical Resource") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(t.getType()) || "Resource".equals(t.getType()), I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Canonical Resource") && ok;
} else { } else {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(t.getType()), I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Canonical Resource") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), VersionUtilities.getCanonicalResourceNames(context.getVersion()).contains(t.getType()), I18nConstants.SD_ED_TYPE_PROFILE_WRONG_TARGET, p, t, code, path, "Canonical Resource") && ok;
} }
} }
} else { } else {
ok = rule(errors, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_NO_TARGET_PROFILE, code) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.SD_ED_TYPE_NO_TARGET_PROFILE, code) && ok;
} }
return ok; return ok;
} }

View File

@ -72,22 +72,22 @@ public class ValueSetValidator extends BaseValidator {
if (parent.isForPublication()) { if (parent.isForPublication()) {
if (isHL7(vs)) { if (isHL7(vs)) {
boolean ok = true; boolean ok = true;
ok = rule(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("url"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "url") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("url"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "url") && ok;
ok = rule(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("version"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "version") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("version"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "version") && ok;
ok = rule(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("title"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "title") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("title"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "title") && ok;
warning(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("name"), I18nConstants.VALUESET_SHAREABLE_EXTRA_MISSING_HL7, "name"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("name"), I18nConstants.VALUESET_SHAREABLE_EXTRA_MISSING_HL7, "name");
ok = rule(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("status"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "status") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("status"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "status") && ok;
ok = rule(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("experimental"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "experimental") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("experimental"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "experimental") && ok;
ok = rule(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("description"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "description") && ok; ok = rule(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("description"), I18nConstants.VALUESET_SHAREABLE_MISSING_HL7, "description") && ok;
return ok; return ok;
} else { } else {
warning(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("url"), I18nConstants.VALUESET_SHAREABLE_MISSING, "url"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("url"), I18nConstants.VALUESET_SHAREABLE_MISSING, "url");
warning(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("version"), I18nConstants.VALUESET_SHAREABLE_MISSING, "version"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("version"), I18nConstants.VALUESET_SHAREABLE_MISSING, "version");
warning(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("title"), I18nConstants.VALUESET_SHAREABLE_MISSING, "title"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("title"), I18nConstants.VALUESET_SHAREABLE_MISSING, "title");
warning(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("name"), I18nConstants.VALUESET_SHAREABLE_EXTRA_MISSING, "name"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("name"), I18nConstants.VALUESET_SHAREABLE_EXTRA_MISSING, "name");
warning(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("status"), I18nConstants.VALUESET_SHAREABLE_MISSING, "status"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("status"), I18nConstants.VALUESET_SHAREABLE_MISSING, "status");
warning(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("experimental"), I18nConstants.VALUESET_SHAREABLE_MISSING, "experimental"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("experimental"), I18nConstants.VALUESET_SHAREABLE_MISSING, "experimental");
warning(errors, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("description"), I18nConstants.VALUESET_SHAREABLE_MISSING, "description"); warning(errors, NO_RULE_DATE, IssueType.REQUIRED, vs.line(), vs.col(), stack.getLiteralPath(), vs.hasChild("description"), I18nConstants.VALUESET_SHAREABLE_MISSING, "description");
} }
} }
return true; return true;
@ -125,17 +125,17 @@ public class ValueSetValidator extends BaseValidator {
Resource rs = context.fetchResource(Resource.class, v); Resource rs = context.fetchResource(Resource.class, v);
if (rs != null) { if (rs != null) {
warning(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), false, I18nConstants.VALUESET_REFERENCE_INVALID_TYPE, v, rs.fhirType()); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, ns.getLiteralPath(), false, I18nConstants.VALUESET_REFERENCE_INVALID_TYPE, v, rs.fhirType());
} else { } else {
// todo: it's possible, at this point, that the txx server knows the value set, but it's not in scope // todo: it's possible, at this point, that the txx server knows the value set, but it's not in scope
// should we handle this case? // should we handle this case?
warning(errors, IssueType.BUSINESSRULE, ns.getLiteralPath(), false, I18nConstants.VALUESET_REFERENCE_UNKNOWN, v); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, ns.getLiteralPath(), false, I18nConstants.VALUESET_REFERENCE_UNKNOWN, v);
} }
} }
i++; i++;
} }
if (valuesets.size() > 1) { if (valuesets.size() > 1) {
warning(errors, IssueType.INFORMATIONAL, stack.getLiteralPath(), false, I18nConstants.VALUESET_IMPORT_UNION_INTERSECTION); warning(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, stack.getLiteralPath(), false, I18nConstants.VALUESET_IMPORT_UNION_INTERSECTION);
} }
List<Element> concepts = include.getChildrenByName("concept"); List<Element> concepts = include.getChildrenByName("concept");
List<Element> filters = include.getChildrenByName("filter"); List<Element> filters = include.getChildrenByName("filter");
@ -165,9 +165,9 @@ public class ValueSetValidator extends BaseValidator {
} }
for (VSCodingValidationRequest cv : batch) { for (VSCodingValidationRequest cv : batch) {
if (version == null) { if (version == null) {
ok = warningOrHint(errors, IssueType.BUSINESSRULE, cv.getStack().getLiteralPath(), cv.getResult().isOk(), !retired, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE, system, cv.getCoding().getCode()) && ok; ok = warningOrHint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, cv.getStack().getLiteralPath(), cv.getResult().isOk(), !retired, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE, system, cv.getCoding().getCode()) && ok;
} else { } else {
ok = warningOrHint(errors, IssueType.BUSINESSRULE, cv.getStack().getLiteralPath(), cv.getResult().isOk(), !retired, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER, system, version, cv.getCoding().getCode()) && ok; ok = warningOrHint(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, cv.getStack().getLiteralPath(), cv.getResult().isOk(), !retired, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER, system, version, cv.getCoding().getCode()) && ok;
} }
} }
} }
@ -180,7 +180,7 @@ public class ValueSetValidator extends BaseValidator {
cf++; cf++;
} }
} else { } else {
warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), filters.size() == 0 && concepts.size() == 0, I18nConstants.VALUESET_NO_SYSTEM_WARNING); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), filters.size() == 0 && concepts.size() == 0, I18nConstants.VALUESET_NO_SYSTEM_WARNING);
} }
return ok; return ok;
} }
@ -190,20 +190,20 @@ public class ValueSetValidator extends BaseValidator {
if (version == null) { if (version == null) {
ValidationResult vv = context.validateCode(ValidationOptions.defaults(), new Coding(system, code, null), null); ValidationResult vv = context.validateCode(ValidationOptions.defaults(), new Coding(system, code, null), null);
if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
warning(errors, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_UNC_SYSTEM_WARNING, system, vv.getMessage()); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_UNC_SYSTEM_WARNING, system, vv.getMessage());
return false; return false;
} else { } else {
boolean ok = vv.isOk(); boolean ok = vv.isOk();
warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), ok, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE, system, code); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), ok, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE, system, code);
} }
} else { } else {
ValidationResult vv = context.validateCode(ValidationOptions.defaults(), new Coding(system, code, null).setVersion(version), null); ValidationResult vv = context.validateCode(ValidationOptions.defaults(), new Coding(system, code, null).setVersion(version), null);
if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { if (vv.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
warning(errors, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_UNC_SYSTEM_WARNING_VER, system+"#"+version, vv.getMessage()); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stackInc.getLiteralPath(), false, I18nConstants.VALUESET_UNC_SYSTEM_WARNING_VER, system+"#"+version, vv.getMessage());
return false; return false;
} else { } else {
boolean ok = vv.isOk(); boolean ok = vv.isOk();
warning(errors, IssueType.BUSINESSRULE, stack.getLiteralPath(), ok, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER, system, version, code); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), ok, I18nConstants.VALUESET_INCLUDE_INVALID_CONCEPT_CODE_VER, system, version, code);
} }
} }
return true; return true;

View File

@ -76,7 +76,7 @@ public class ProfileValidator extends BaseValidator {
protected boolean rule(List<ValidationMessage> errors, IssueType type, String path, boolean b, String msg) { protected boolean rule(List<ValidationMessage> errors, IssueType type, String path, boolean b, String msg) {
String rn = path.contains(".") ? path.substring(0, path.indexOf(".")) : path; String rn = path.contains(".") ? path.substring(0, path.indexOf(".")) : path;
return super.ruleHtml(errors, type, path, b, msg, "<a href=\""+(rn.toLowerCase())+".html\">"+rn+"</a>: "+Utilities.escapeXml(msg)); return super.ruleHtml(errors, NO_RULE_DATE, type, path, b, msg, "<a href=\""+(rn.toLowerCase())+".html\">"+rn+"</a>: "+Utilities.escapeXml(msg));
} }
public List<ValidationMessage> validate(StructureDefinition profile, boolean forBuild) { public List<ValidationMessage> validate(StructureDefinition profile, boolean forBuild) {
@ -84,28 +84,28 @@ public class ProfileValidator extends BaseValidator {
// must have a FHIR version- GF#3160 // must have a FHIR version- GF#3160
String s = (profile.getKind() == StructureDefinitionKind.LOGICAL) ? "Logical Models" : "Profiles"; String s = (profile.getKind() == StructureDefinitionKind.LOGICAL) ? "Logical Models" : "Profiles";
warning(errors, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasFhirVersion(), s+" SHOULD state the FHIR Version on which they are based"); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasFhirVersion(), s+" SHOULD state the FHIR Version on which they are based");
warning(errors, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasVersion(), s+" SHOULD state their own version"); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getUrl(), profile.hasVersion(), s+" SHOULD state their own version");
// extensions must be defined // extensions must be defined
for (ElementDefinition ec : profile.getDifferential().getElement()) for (ElementDefinition ec : profile.getDifferential().getElement())
checkExtensions(profile, errors, "differential", ec); checkExtensions(profile, errors, "differential", ec);
rule(errors, IssueType.STRUCTURE, profile.getId(), profile.hasSnapshot(), "missing Snapshot at "+profile.getName()+"."+profile.getName()); rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, profile.getId(), profile.hasSnapshot(), "missing Snapshot at "+profile.getName()+"."+profile.getName());
for (ElementDefinition ec : profile.getSnapshot().getElement()) for (ElementDefinition ec : profile.getSnapshot().getElement())
checkExtensions(profile, errors, "snapshot", ec); checkExtensions(profile, errors, "snapshot", ec);
if (rule(errors, IssueType.STRUCTURE, profile.getId(), profile.hasSnapshot(), "A snapshot is required")) { if (rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, profile.getId(), profile.hasSnapshot(), "A snapshot is required")) {
Hashtable<String, ElementDefinition> snapshotElements = new Hashtable<String, ElementDefinition>(); Hashtable<String, ElementDefinition> snapshotElements = new Hashtable<String, ElementDefinition>();
for (ElementDefinition ed : profile.getSnapshot().getElement()) { for (ElementDefinition ed : profile.getSnapshot().getElement()) {
snapshotElements.put(ed.getId(), ed); snapshotElements.put(ed.getId(), ed);
for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) { for (ElementDefinitionConstraintComponent inv : ed.getConstraint()) {
if (forBuild) { if (forBuild) {
if (!inExemptList(inv.getKey())) { if (!inExemptList(inv.getKey())) {
if (rule(errors, IssueType.BUSINESSRULE, profile.getId()+"::"+ed.getPath()+"::"+inv.getKey(), inv.hasExpression(), "The invariant has no FHIR Path expression ("+inv.getXpath()+")")) { if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getId()+"::"+ed.getPath()+"::"+inv.getKey(), inv.hasExpression(), "The invariant has no FHIR Path expression ("+inv.getXpath()+")")) {
// try { // try {
// fpe.check(null, profile.getType(), ed.getPath(), inv.getExpression()); // , inv.hasXpath() && inv.getXpath().startsWith("@value") // fpe.check(null, profile.getType(), ed.getPath(), inv.getExpression()); // , inv.hasXpath() && inv.getXpath().startsWith("@value")
// } catch (Exception e) { // } catch (Exception e) {
// // rule(errors, IssueType.STRUCTURE, profile.getId()+"::"+ed.getPath()+"::"+inv.getId(), false, e.getMessage()); // // rule(errors, UNKNOWN_DATE_TIME, IssueType.STRUCTURE, profile.getId()+"::"+ed.getPath()+"::"+inv.getId(), false, e.getMessage());
// } // }
} }
} }
@ -118,11 +118,11 @@ public class ProfileValidator extends BaseValidator {
throw new Error("Diff Element is null - this is not an expected thing"); throw new Error("Diff Element is null - this is not an expected thing");
ElementDefinition snapElement = snapshotElements.get(diffElement.getId()); ElementDefinition snapElement = snapshotElements.get(diffElement.getId());
if (snapElement!=null) { // Happens with profiles in the main build - should be able to fix once snapshot generation is fixed - Lloyd if (snapElement!=null) { // Happens with profiles in the main build - should be able to fix once snapshot generation is fixed - Lloyd
warning(errors, IssueType.BUSINESSRULE, diffElement.getId(), !checkMustSupport || snapElement.hasMustSupport(), "Elements included in the differential should declare mustSupport"); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, diffElement.getId(), !checkMustSupport || snapElement.hasMustSupport(), "Elements included in the differential should declare mustSupport");
if (checkAggregation) { if (checkAggregation) {
for (TypeRefComponent type : snapElement.getType()) { for (TypeRefComponent type : snapElement.getType()) {
if ("http://hl7.org/fhir/Reference".equals(type.getWorkingCode()) || "http://hl7.org/fhir/canonical".equals(type.getWorkingCode())) { if ("http://hl7.org/fhir/Reference".equals(type.getWorkingCode()) || "http://hl7.org/fhir/canonical".equals(type.getWorkingCode())) {
warning(errors, IssueType.BUSINESSRULE, diffElement.getId(), type.hasAggregation(), "Elements with type Reference or canonical should declare aggregation"); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, diffElement.getId(), type.hasAggregation(), "Elements with type Reference or canonical should declare aggregation");
} }
} }
} }
@ -145,7 +145,7 @@ public class ProfileValidator extends BaseValidator {
if (defn == null) { if (defn == null) {
defn = getXverExt(profile, errors, url); defn = getXverExt(profile, errors, url);
} }
rule(errors, IssueType.BUSINESSRULE, profile.getId(), defn != null, "Unable to find Extension '"+url+"' referenced at "+profile.getUrl()+" "+kind+" "+ec.getPath()+" ("+ec.getSliceName()+")"); rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, profile.getId(), defn != null, "Unable to find Extension '"+url+"' referenced at "+profile.getUrl()+" "+kind+" "+ec.getPath()+" ("+ec.getSliceName()+")");
} }
} }