Fix issue with discriminating by address and human name

This commit is contained in:
Grahame Grieve 2020-09-14 18:10:31 +10:00
parent db8f28ea51
commit 9fc8b35797
4 changed files with 128 additions and 3 deletions

View File

@ -528,6 +528,8 @@ public class I18nConstants {
public static final String UNSUPPORTED_FIXED_PATTERN_TYPE_FOR_DISCRIMINATOR_FOR_SLICE__ = "Unsupported_fixed_pattern_type_for_discriminator_for_slice__"; public static final String UNSUPPORTED_FIXED_PATTERN_TYPE_FOR_DISCRIMINATOR_FOR_SLICE__ = "Unsupported_fixed_pattern_type_for_discriminator_for_slice__";
public static final String UNSUPPORTED_FIXED_VALUE_TYPE_FOR_DISCRIMINATOR_FOR_SLICE__ = "Unsupported_fixed_value_type_for_discriminator_for_slice__"; public static final String UNSUPPORTED_FIXED_VALUE_TYPE_FOR_DISCRIMINATOR_FOR_SLICE__ = "Unsupported_fixed_value_type_for_discriminator_for_slice__";
public static final String UNSUPPORTED_IDENTIFIER_PATTERN__EXTENSIONS_ARE_NOT_ALLOWED__FOR_DISCRIMINATOR_FOR_SLICE_ = "Unsupported_Identifier_pattern__extensions_are_not_allowed__for_discriminator_for_slice_"; public static final String UNSUPPORTED_IDENTIFIER_PATTERN__EXTENSIONS_ARE_NOT_ALLOWED__FOR_DISCRIMINATOR_FOR_SLICE_ = "Unsupported_Identifier_pattern__extensions_are_not_allowed__for_discriminator_for_slice_";
public static final String UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = "UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE";
public static final String UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = "UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE";
public static final String UNSUPPORTED_VERSION_R1 = "Unsupported_version_R1"; public static final String UNSUPPORTED_VERSION_R1 = "Unsupported_version_R1";
public static final String UNSUPPORTED_VERSION_R2 = "Unsupported_version_R2"; public static final String UNSUPPORTED_VERSION_R2 = "Unsupported_version_R2";
public static final String UNSUPPORTED_VERSION_R2B = "Unsupported_version_R2B"; public static final String UNSUPPORTED_VERSION_R2B = "Unsupported_version_R2B";

View File

@ -607,3 +607,5 @@ FHIRPATH_FOCUS_PLURAL = Error evaluating FHIRPath expression: focus for {0} has
REFERENCE_REF_SUSPICIOUS = The syntax of the reference ''{0}'' looks incorrect, and it should be checked REFERENCE_REF_SUSPICIOUS = The syntax of the reference ''{0}'' looks incorrect, and it should be checked
TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS = UCUM Codes that contain human readable annotations like {0} can be misleading. Best Practice is not to use annotations in the UCUM code, and rather to make sure that Quantity.unit is correctly human readable TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS = UCUM Codes that contain human readable annotations like {0} can be misleading. Best Practice is not to use annotations in the UCUM code, and rather to make sure that Quantity.unit is correctly human readable
XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA = Illegal element name inside in a paragraph in the XHTML (''{0}'') XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA = Illegal element name inside in a paragraph in the XHTML (''{0}'')
UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = Unsupported property {3} on type {2} for pattern for discriminator({0}) for slice {1}
UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE = Unsupported: no properties with values found on type {2} for pattern for discriminator({0}) for slice {1}

View File

@ -3436,8 +3436,16 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
Identifier ii = (Identifier) pattern; Identifier ii = (Identifier) pattern;
expression.append(" and "); expression.append(" and ");
buildIdentifierExpression(ed, expression, discriminator, ii); buildIdentifierExpression(ed, expression, discriminator, ii);
} else if (pattern instanceof HumanName) {
HumanName name = (HumanName) pattern;
expression.append(" and ");
buildHumanNameExpression(ed, expression, discriminator, name);
} else if (pattern instanceof Address) {
Address add = (Address) pattern;
expression.append(" and ");
buildAddressExpression(ed, expression, discriminator, add);
} else { } else {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_FIXED_PATTERN_TYPE_FOR_DISCRIMINATOR_FOR_SLICE__, discriminator, ed.getId(), pattern.getClass().getName())); throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_FIXED_PATTERN_TYPE_FOR_DISCRIMINATOR_FOR_SLICE__, discriminator, ed.getId(), pattern.fhirType()));
} }
} }
@ -3472,6 +3480,101 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
expression.append(" and "); expression.append(" and ");
buildCodeableConceptExpression(ed, expression, TYPE, ii.getType()); buildCodeableConceptExpression(ed, expression, TYPE, ii.getType());
} }
if (first) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), ii.fhirType()));
}
expression.append(").exists()");
}
private void buildHumanNameExpression(ElementDefinition ed, StringBuilder expression, String discriminator, HumanName name) throws DefinitionException {
if (name.hasExtension())
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN__EXTENSIONS_ARE_NOT_ALLOWED__FOR_DISCRIMINATOR_FOR_SLICE_, discriminator, ed.getId()));
boolean first = true;
expression.append(discriminator + ".where(");
if (name.hasUse()) {
first = false;
expression.append("use = '" + name.getUse().toCode() + "'");
}
if (name.hasText()) {
if (first)
first = false;
else
expression.append(" and ");
expression.append("text = '" + name.getText() + "'");
}
if (name.hasFamily()) {
if (first)
first = false;
else
expression.append(" and ");
expression.append("family = '" + name.getFamily() + "'");
}
if (name.hasGiven()) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), name.fhirType(), "given"));
}
if (name.hasPrefix()) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), name.fhirType(), "prefix"));
}
if (name.hasSuffix()) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), name.fhirType(), "suffix"));
}
if (name.hasPeriod()) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), name.fhirType(), "period"));
}
if (first) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), name.fhirType()));
}
expression.append(").exists()");
}
private void buildAddressExpression(ElementDefinition ed, StringBuilder expression, String discriminator, Address add) throws DefinitionException {
if (add.hasExtension()) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN__EXTENSIONS_ARE_NOT_ALLOWED__FOR_DISCRIMINATOR_FOR_SLICE_, discriminator, ed.getId()));
}
boolean first = true;
expression.append(discriminator + ".where(");
if (add.hasUse()) {
first = false;
expression.append("use = '" + add.getUse().toCode() + "'");
}
if (add.hasType()) {
if (first) first = false; else expression.append(" and ");
expression.append("type = '" + add.getType().toCode() + "'");
}
if (add.hasText()) {
if (first) first = false; else expression.append(" and ");
expression.append("text = '" + add.getText() + "'");
}
if (add.hasCity()) {
if (first) first = false; else expression.append(" and ");
expression.append("city = '" + add.getCity() + "'");
}
if (add.hasDistrict()) {
if (first) first = false; else expression.append(" and ");
expression.append("district = '" + add.getDistrict() + "'");
}
if (add.hasState()) {
if (first) first = false; else expression.append(" and ");
expression.append("state = '" + add.getState() + "'");
}
if (add.hasPostalCode()) {
if (first) first = false; else expression.append(" and ");
expression.append("postalCode = '" + add.getPostalCode() + "'");
}
if (add.hasCountry()) {
if (first) first = false; else expression.append(" and ");
expression.append("country = '" + add.getCountry() + "'");
}
if (add.hasLine()) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), add.fhirType(), "line"));
}
if (add.hasPeriod()) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), add.fhirType(), "period"));
}
if (first) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), add.fhirType()));
}
expression.append(").exists()"); expression.append(").exists()");
} }
@ -3510,6 +3613,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
else expression.append(" and "); else expression.append(" and ");
expression.append("display = '" + c.getDisplay() + "'"); expression.append("display = '" + c.getDisplay() + "'");
} }
if (first) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), cc.fhirType()));
}
expression.append(").exists()"); expression.append(").exists()");
} }
} }
@ -3539,6 +3645,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
else expression.append(" and "); else expression.append(" and ");
expression.append("display = '" + c.getDisplay() + "'"); expression.append("display = '" + c.getDisplay() + "'");
} }
if (first) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNSUPPORTED_IDENTIFIER_PATTERN_NO_PROPERTY_NOT_SUPPORTED_FOR_DISCRIMINATOR_FOR_SLICE, discriminator, ed.getId(), c.fhirType()));
}
expression.append(").exists()"); expression.append(").exists()");
} }
@ -4137,7 +4246,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
} }
} }
} else if (type.equals("Resource")) { } else if (type.equals("Resource") || isResource(type)) {
validateContains(hostContext, errors, ei.getPath(), ei.definition, definition, resource, ei.getElement(), localStack, idStatusForEntry(element, ei)); // if validateContains(hostContext, errors, ei.getPath(), ei.definition, definition, resource, ei.getElement(), localStack, idStatusForEntry(element, ei)); // if
elementValidated = true; elementValidated = true;
// (str.matches(".*([.,/])work\\1$")) // (str.matches(".*([.,/])work\\1$"))
@ -4228,7 +4337,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (!elementValidated) { if (!elementValidated) {
if (ei.getElement().getSpecial() == SpecialElement.BUNDLE_ENTRY || ei.getElement().getSpecial() == SpecialElement.BUNDLE_OUTCOME || ei.getElement().getSpecial() == SpecialElement.PARAMETER) if (ei.getElement().getSpecial() == SpecialElement.BUNDLE_ENTRY || ei.getElement().getSpecial() == SpecialElement.BUNDLE_OUTCOME || ei.getElement().getSpecial() == SpecialElement.PARAMETER)
validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, ei.definition, ei.getElement(), ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension); validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, ei.definition, ei.getElement(), ei.getElement(), type, localStack.resetIds(), thisIsCodeableConcept, checkDisplay, thisExtension);
else else
validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, ei.definition, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension); validateElement(hostContext, errors, p, getElementByTail(p, tail), profile, ei.definition, resource, ei.getElement(), type, localStack, thisIsCodeableConcept, checkDisplay, thisExtension);
} }
@ -4242,6 +4351,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
} }
private boolean isResource(String type) {
StructureDefinition sd = context.fetchTypeDefinition(type);
return sd != null && sd.getKind().equals(StructureDefinitionKind.RESOURCE);
}
private void trackUsage(StructureDefinition profile, ValidatorHostContext hostContext, Element element) { private void trackUsage(StructureDefinition profile, ValidatorHostContext hostContext, Element element) {
if (tracker != null) { if (tracker != null) {
tracker.recordProfileUsage(profile, hostContext.getAppContext(), element); tracker.recordProfileUsage(profile, hostContext.getAppContext(), element);

View File

@ -259,6 +259,8 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
checkOutcomes(errorsProfile, profile, filename, name); checkOutcomes(errorsProfile, profile, filename, name);
} }
if (content.has("logical")) { if (content.has("logical")) {
System.out.print("** Logical: ");
JsonObject logical = content.getAsJsonObject("logical"); JsonObject logical = content.getAsJsonObject("logical");
if (logical.has("supporting")) { if (logical.has("supporting")) {
for (JsonElement e : logical.getAsJsonArray("supporting")) { for (JsonElement e : logical.getAsJsonArray("supporting")) {
@ -271,6 +273,11 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
val.getContext().cacheResource(mr); val.getContext().cacheResource(mr);
} }
} }
if (logical.has("packages")) {
for (JsonElement e : logical.getAsJsonArray("packages")) {
vCurr.loadIg(e.getAsString(), true);
}
}
List<ValidationMessage> errorsLogical = new ArrayList<ValidationMessage>(); List<ValidationMessage> errorsLogical = new ArrayList<ValidationMessage>();
Element le = val.validate(null, errorsLogical, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), (name.endsWith(".json")) ? FhirFormat.JSON : FhirFormat.XML); Element le = val.validate(null, errorsLogical, IOUtils.toInputStream(testCaseContent, Charsets.UTF_8), (name.endsWith(".json")) ? FhirFormat.JSON : FhirFormat.XML);
if (logical.has("expressions")) { if (logical.has("expressions")) {