fix slicing by type and profile to allow multiple options per slice
This commit is contained in:
parent
afd9e7a471
commit
0c4da028b3
|
@ -604,7 +604,7 @@ public class FHIRPathEngine {
|
|||
warnings.addAll(typeWarnings);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, TypeDetails types, ExpressionNode expr, List<IssueMessage> warnings) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
typeWarnings.clear();
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, null, true, false, expr);
|
||||
|
@ -612,6 +612,13 @@ public class FHIRPathEngine {
|
|||
return res;
|
||||
}
|
||||
|
||||
public TypeDetails checkOnTypes(Object appContext, String resourceType, TypeDetails types, ExpressionNode expr, List<IssueMessage> warnings, boolean canBeNone) throws FHIRLexerException, PathEngineException, DefinitionException {
|
||||
typeWarnings.clear();
|
||||
TypeDetails res = executeType(new ExecutionTypeContext(appContext, resourceType, types, types), types, expr, null, true, canBeNone, expr);
|
||||
warnings.addAll(typeWarnings);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* check that paths referred to in the ExpressionNode are valid
|
||||
*
|
||||
|
@ -6585,7 +6592,7 @@ public class FHIRPathEngine {
|
|||
|
||||
|
||||
/** given an element definition in a profile, what element contains the differentiating fixed
|
||||
* for the element, given the differentiating expresssion. The expression is only allowed to
|
||||
* for the element, given the differentiating expression. The expression is only allowed to
|
||||
* use a subset of FHIRPath
|
||||
*
|
||||
* @param profile
|
||||
|
|
|
@ -178,7 +178,6 @@ public class I18nConstants {
|
|||
public static final String DIFFERENTIAL_WALKS_INTO____BUT_THE_BASE_DOES_NOT_AND_THERE_IS_NOT_A_SINGLE_FIXED_TYPE_THE_TYPE_IS__THIS_IS_NOT_HANDLED_YET = "Differential_walks_into____but_the_base_does_not_and_there_is_not_a_single_fixed_type_The_type_is__This_is_not_handled_yet";
|
||||
public static final String DISCRIMINATOR_BAD_PATH = "DISCRIMINATOR_BAD_PATH";
|
||||
public static final String DISCRIMINATOR__IS_BASED_ON_ELEMENT_EXISTENCE_BUT_SLICE__NEITHER_SETS_MIN1_OR_MAX0 = "Discriminator__is_based_on_element_existence_but_slice__neither_sets_min1_or_max0";
|
||||
public static final String DISCRIMINATOR__IS_BASED_ON_TYPE_BUT_SLICE__IN__HAS_MULTIPLE_TYPES = "Discriminator__is_based_on_type_but_slice__in__has_multiple_types";
|
||||
public static final String DISCRIMINATOR__IS_BASED_ON_TYPE_BUT_SLICE__IN__HAS_NO_TYPES = "Discriminator__is_based_on_type_but_slice__in__has_no_types";
|
||||
public static final String DISPLAY_NAME_FOR__SHOULD_BE_ONE_OF__INSTEAD_OF = "Display_Name_for__should_be_one_of__instead_of";
|
||||
public static final String DISPLAY_NAME_WS_FOR__SHOULD_BE_ONE_OF__INSTEAD_OF = "Display_Name_WS_for__should_be_one_of__instead_of";
|
||||
|
@ -475,7 +474,6 @@ public class I18nConstants {
|
|||
public static final String PROBLEM_PROCESSING_EXPRESSION__IN_PROFILE__PATH__ = "Problem_processing_expression__in_profile__path__";
|
||||
public static final String PROFILE_BASED_DISCRIMINATORS_MUST_HAVE_A_TYPE_WITH_A_PROFILE__IN_PROFILE_ = "Profile_based_discriminators_must_have_a_type_with_a_profile__in_profile_";
|
||||
public static final String PROFILE_BASED_DISCRIMINATORS_MUST_HAVE_A_TYPE__IN_PROFILE_ = "Profile_based_discriminators_must_have_a_type__in_profile_";
|
||||
public static final String PROFILE_BASED_DISCRIMINATORS_MUST_HAVE_ONLY_ONE_TYPE__IN_PROFILE = "Profile_based_discriminators_must_have_only_one_type__in_profile";
|
||||
public static final String PROFILE_EXT_NOT_HERE = "Profile_EXT_Not_Here";
|
||||
public static final String PROFILE_VAL_MISSINGELEMENT = "Profile_VAL_MissingElement";
|
||||
public static final String PROFILE_VAL_NOTALLOWED = "Profile_VAL_NotAllowed";
|
||||
|
@ -1122,4 +1120,9 @@ public class I18nConstants {
|
|||
public static final String CODESYSTEM_CS_COMPLETE_AND_EMPTY = "CODESYSTEM_CS_COMPLETE_AND_EMPTY";
|
||||
public static final String VALIDATION_VAL_VERSION_NOHASH = "VALIDATION_VAL_VERSION_NOHASH";
|
||||
public static final String PRIMITIVE_TOO_SHORT = "PRIMITIVE_TOO_SHORT";
|
||||
public static final String CANONICAL_MULTIPLE_VERSIONS_KNOWN = "CANONICAL_MULTIPLE_VERSIONS_KNOWN";
|
||||
public static final String SD_PATH_NO_SLICING = "SD_PATH_NO_SLICING";
|
||||
public static final String SD_PATH_SLICING_DEPRECATED = "SD_PATH_SLICING_DEPRECATED";
|
||||
public static final String SD_PATH_NOT_VALID = "SD_PATH_NOT_VALID";
|
||||
public static final String SD_PATH_ERROR = "SD_PATH_ERROR";
|
||||
}
|
||||
|
|
|
@ -179,8 +179,6 @@ Did_not_find_type_root_ = Did not find type root: {0}
|
|||
Differential_does_not_have_a_slice__b_of_____in_profile_ = Differential in profile {5} does not have a slice at {6} (on {0}, position {1} of {2} / {3} / {4})
|
||||
Differential_walks_into____but_the_base_does_not_and_there_is_not_a_single_fixed_type_The_type_is__This_is_not_handled_yet = Differential walks into ''{0} (@ {1})'', but the base does not, and there is not a single fixed type. The type is {2}. This is not handled yet
|
||||
Discriminator__is_based_on_element_existence_but_slice__neither_sets_min1_or_max0 = Discriminator ({0}) is based on element existence, but slice {1} neither sets min>=1 or max=0
|
||||
Discriminator__is_based_on_type_but_slice__in__has_multiple_types_one =
|
||||
Discriminator__is_based_on_type_but_slice__in__has_multiple_types_other = Discriminator ({1}) is based on type, but slice {2} in {3} has {0} types: {4}
|
||||
Discriminator__is_based_on_type_but_slice__in__has_no_types = Discriminator ({0}) is based on type, but slice {1} in {2} has no types
|
||||
Display_Name_WS_for__should_be_one_of__instead_of_one = Wrong whitespace in Display Name ''{4}'' for {1}#{2}. Valid display is {3} (for the language(s) ''{5}'')
|
||||
Display_Name_WS_for__should_be_one_of__instead_of_other = Wrong whitespace in Display Name ''{4}'' for {1}#{2}. Valid display is one of {0} choices: {3} (for the language(s) ''{5}'')
|
||||
|
@ -486,8 +484,6 @@ Profile___has_no_base_and_no_snapshot = Profile {0} ({1}) has no base and no sna
|
|||
Profile__does_not_match_for__because_of_the_following_profile_issues__ = Profile {0} does not match for {1} because of the following profile issues: {2}
|
||||
Profile_based_discriminators_must_have_a_type__in_profile_ = Profile based discriminators must have a type ({0} in profile {1})
|
||||
Profile_based_discriminators_must_have_a_type_with_a_profile__in_profile_ = Profile based discriminators must have a type with a profile ({0} in profile {1})
|
||||
Profile_based_discriminators_must_have_only_one_type__in_profile_one =
|
||||
Profile_based_discriminators_must_have_only_one_type__in_profile_other = Profile based discriminators must have only one type ({1} in profile {2}) but found {0} types
|
||||
QUESTIONNAIRE_QR_ITEM_BADOPTION_CS = The code provided {1} cannot be validated in the options value set ({2}) in the questionnaire because the system {0} could not be found
|
||||
QUESTIONNAIRE_Q_DERIVATION_TYPE_IGNORED = The derivation type ''{0}'' means that no derivation checking has been performed against this questionnaire
|
||||
QUESTIONNAIRE_Q_DERIVATION_TYPE_UNKNOWN = The derivation type ''{0}'' is unknown, which means that no derivation checking has been performed against this questionnaire
|
||||
|
@ -1090,7 +1086,7 @@ XHTML_XHTML_NS_InValid = Wrong namespace on the XHTML (''{0}'', should be ''{1}'
|
|||
XHTML_XHTML_Name_Invalid = Wrong name on the XHTML (''{0}'') - must start with div
|
||||
XSI_TYPE_UNNECESSARY = xsi:type is unnecessary at this point
|
||||
XSI_TYPE_WRONG = The xsi:type value ''{0}'' is wrong (should be ''{1}''). Note that xsi:type is unnecessary at this point
|
||||
_DT_Fixed_Wrong = Value is ''{0}'' but must be ''{1}''{2}
|
||||
_DT_Fixed_Wrong = Value is ''{0}'' but is fixed to ''{1}'' in the profile {2}
|
||||
_has_children__and_multiple_types__in_profile_ = {0} has children ({1}) and multiple types ({2}) in profile {3}
|
||||
_has_children__for_type__in_profile__but_cant_find_type = {0} has children ({1}) for type {2} in profile {3}, but can''t find type
|
||||
_has_no_children__and_no_types_in_profile_ = {0} has no children ({1}) and no types in profile {2}
|
||||
|
@ -1155,4 +1151,8 @@ SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_TYPE = The Usage Context value must be of
|
|||
CODESYSTEM_CS_COMPLETE_AND_EMPTY = When a CodeSystem has content = ''complete'', it doesn't make sense for there to be no concepts defined
|
||||
VALIDATION_VAL_VERSION_NOHASH = Version ''{0}'' contains a ''#'', which as this character is used in some URLs to separate the version and the fragment id. When version does include '#', systems will not be able to parse the URL
|
||||
PRIMITIVE_TOO_SHORT = Value ''{0}'' is shorter than permitted minimum length of {1}
|
||||
|
||||
CANONICAL_MULTIPLE_VERSIONS_KNOWN = The version {2} for the {0} {1} is not known. These versions are known: {3}
|
||||
SD_PATH_SLICING_DEPRECATED = The discriminator type ''{0}'' has been deprecated. Use type=fixed with a pattern[x] instead
|
||||
SD_PATH_NOT_VALID = The discriminator path ''{0}'' does not appear to be valid for the element that is being sliced ''{1}''
|
||||
SD_PATH_ERROR = The discriminator path ''{0}'' does not appear to be valid for the element that is being sliced ''{1}'': {2}
|
||||
|
||||
|
|
|
@ -1047,7 +1047,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
private boolean check(String v1, String v2) {
|
||||
return v1 == null ? Utilities.noString(v1) : v1.equals(v2);
|
||||
boolean res = v1 == null ? Utilities.noString(v1) : v1.equals(v2);
|
||||
return res;
|
||||
}
|
||||
|
||||
private boolean checkAddress(List<ValidationMessage> errors, String path, Element focus, Address fixed, String fixedSource, boolean pattern, String context) {
|
||||
|
@ -3209,10 +3210,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
if (context.hasFixed()) {
|
||||
ok = checkFixedValue(errors, path, e, context.getFixed(), profile.getVersionedUrl(), context.getSliceName(), null, false, "") && ok;
|
||||
ok = checkFixedValue(errors, path, e, context.getFixed(), profile.getVersionedUrl(), context.getSliceName(), null, false, profile.getVersionedUrl()+"#"+context.getId()) && ok;
|
||||
}
|
||||
if (context.hasPattern()) {
|
||||
ok = checkFixedValue(errors, path, e, context.getPattern(), profile.getVersionedUrl(), context.getSliceName(), null, true, "") && ok;
|
||||
ok = checkFixedValue(errors, path, e, context.getPattern(), profile.getVersionedUrl(), context.getSliceName(), null, true, profile.getVersionedUrl()+"#"+context.getId()) && ok;
|
||||
}
|
||||
|
||||
if (ok && !ID_EXEMPT_LIST.contains(e.fhirType())) { // ids get checked elsewhere
|
||||
|
@ -5129,12 +5130,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
if ("0".equals(criteriaElement.getMax())) {
|
||||
expression.append(" and " + discriminator + ".empty()");
|
||||
} else if (s.getType() == DiscriminatorType.TYPE) {
|
||||
String type = null;
|
||||
if (!criteriaElement.getPath().contains("[") && discriminator.contains("[")) {
|
||||
discriminator = discriminator.substring(0, discriminator.indexOf('['));
|
||||
String lastNode = tail(discriminator);
|
||||
type = makeTypeForFHIRPath(criteriaElement.getPath()).substring(lastNode.length());
|
||||
String type = makeTypeForFHIRPath(criteriaElement.getPath()).substring(lastNode.length());
|
||||
expression.append(" and " + discriminator + " is " + type);
|
||||
} else if (!criteriaElement.hasType() || criteriaElement.getType().size() == 1) {
|
||||
String type = null;
|
||||
if (discriminator.contains("["))
|
||||
discriminator = discriminator.substring(0, discriminator.indexOf('['));
|
||||
if (criteriaElement.hasType()) {
|
||||
|
@ -5144,23 +5146,25 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
} else {
|
||||
throw new DefinitionException(context.formatMessage(I18nConstants.DISCRIMINATOR__IS_BASED_ON_TYPE_BUT_SLICE__IN__HAS_NO_TYPES, discriminator, ed.getId(), profile.getVersionedUrl()));
|
||||
}
|
||||
expression.append(" and " + discriminator + " is " + type);
|
||||
} else if (criteriaElement.getType().size() > 1) {
|
||||
throw new DefinitionException(context.formatMessagePlural(criteriaElement.getType().size(), I18nConstants.DISCRIMINATOR__IS_BASED_ON_TYPE_BUT_SLICE__IN__HAS_MULTIPLE_TYPES, discriminator, ed.getId(), profile.getVersionedUrl(), criteriaElement.typeSummary()));
|
||||
CommaSeparatedStringBuilder cb = new CommaSeparatedStringBuilder(" or ");
|
||||
for (TypeRefComponent tr : criteriaElement.getType()) {
|
||||
String type = makeTypeForFHIRPath(tr.getWorkingCode());
|
||||
cb.append(discriminator + " is " + type);
|
||||
}
|
||||
expression.append(" and (" + cb.toString()+")");
|
||||
} else
|
||||
throw new DefinitionException(context.formatMessage(I18nConstants.DISCRIMINATOR__IS_BASED_ON_TYPE_BUT_SLICE__IN__HAS_NO_TYPES, discriminator, ed.getId(), profile.getVersionedUrl()));
|
||||
if (discriminator.isEmpty()) {
|
||||
expression.append(" and $this is " + type);
|
||||
} else {
|
||||
expression.append(" and " + discriminator + " is " + type);
|
||||
}
|
||||
} else if (s.getType() == DiscriminatorType.PROFILE) {
|
||||
if (criteriaElement.getType().size() == 0) {
|
||||
throw new DefinitionException(context.formatMessage(I18nConstants.PROFILE_BASED_DISCRIMINATORS_MUST_HAVE_A_TYPE__IN_PROFILE_, criteriaElement.getId(), profile.getVersionedUrl()));
|
||||
}
|
||||
if (criteriaElement.getType().size() != 1) {
|
||||
throw new DefinitionException(context.formatMessagePlural(criteriaElement.getType().size(), I18nConstants.PROFILE_BASED_DISCRIMINATORS_MUST_HAVE_ONLY_ONE_TYPE__IN_PROFILE, criteriaElement.getId(), profile.getVersionedUrl()));
|
||||
List<CanonicalType> list = new ArrayList<>();
|
||||
boolean ref = discriminator.endsWith(".resolve()") || discriminator.equals("resolve()");
|
||||
for (TypeRefComponent tr : criteriaElement.getType()) {
|
||||
list.addAll(ref ? tr.getTargetProfile() : tr.getProfile());
|
||||
}
|
||||
List<CanonicalType> list = discriminator.endsWith(".resolve()") || discriminator.equals("resolve()") ? criteriaElement.getType().get(0).getTargetProfile() : criteriaElement.getType().get(0).getProfile();
|
||||
if (list.size() == 0) {
|
||||
// we don't have to find something
|
||||
// throw new DefinitionException(context.formatMessage(I18nConstants.PROFILE_BASED_DISCRIMINATORS_MUST_HAVE_A_TYPE_WITH_A_PROFILE__IN_PROFILE_, criteriaElement.getId(), profile.getVersionedUrl()));
|
||||
|
@ -6357,10 +6361,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
ValidationInfo vi = element.addDefinition(profile, definition, mode);
|
||||
|
||||
if (definition.getFixed() != null) {
|
||||
ok = checkFixedValue(errors, stack.getLiteralPath(), element, definition.getFixed(), profile.getVersionedUrl(), definition.getSliceName(), null, false, "") && ok;
|
||||
ok = checkFixedValue(errors, stack.getLiteralPath(), element, definition.getFixed(), profile.getVersionedUrl(), definition.getSliceName(), null, false, profile.getVersionedUrl()+"#"+definition.getId()) && ok;
|
||||
}
|
||||
if (definition.getPattern() != null) {
|
||||
ok = checkFixedValue(errors, stack.getLiteralPath(), element, definition.getPattern(), profile.getVersionedUrl(), definition.getSliceName(), null, true, "") && ok;
|
||||
ok = checkFixedValue(errors, stack.getLiteralPath(), element, definition.getPattern(), profile.getVersionedUrl(), definition.getSliceName(), null, true, profile.getVersionedUrl()+"#"+definition.getId()) && ok;
|
||||
}
|
||||
|
||||
// get the list of direct defined children, including slices
|
||||
|
@ -6644,10 +6648,10 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
ok = checkPrimitive(valContext, errors, ei.getPath(), type, checkDefn, ei.getElement(), profile, localStack, stack, valContext.getRootResource()) && ok;
|
||||
} else {
|
||||
if (checkDefn.hasFixed()) {
|
||||
ok = checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getFixed(), profile.getVersionedUrl(), checkDefn.getSliceName(), null, false, "") && ok;
|
||||
ok = checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getFixed(), profile.getVersionedUrl(), checkDefn.getSliceName(), null, false, profile.getVersionedUrl()+"#"+definition.getId()) && ok;
|
||||
}
|
||||
if (checkDefn.hasPattern()) {
|
||||
ok = checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getPattern(), profile.getVersionedUrl(), checkDefn.getSliceName(), null, true, "") && ok;
|
||||
ok = checkFixedValue(errors, ei.getPath(), ei.getElement(), checkDefn.getPattern(), profile.getVersionedUrl(), checkDefn.getSliceName(), null, true, profile.getVersionedUrl()+"#"+definition.getId()) && ok;
|
||||
}
|
||||
}
|
||||
if (type.equals("Identifier")) {
|
||||
|
@ -7600,7 +7604,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
private boolean valueMatchesCriteria(Element value, ElementDefinition criteria, StructureDefinition profile) throws FHIRException {
|
||||
if (criteria.hasFixed()) {
|
||||
List<ValidationMessage> msgs = new ArrayList<ValidationMessage>();
|
||||
checkFixedValue(msgs, "{virtual}", value, criteria.getFixed(), profile.getVersionedUrl(), "value", null, false, "");
|
||||
checkFixedValue(msgs, "{virtual}", value, criteria.getFixed(), profile.getVersionedUrl(), "value", null, false, profile.getVersionedUrl()+"#"+criteria.getId());
|
||||
return msgs.size() == 0;
|
||||
} else if (criteria.hasBinding() && criteria.getBinding().getStrength() == BindingStrength.REQUIRED && criteria.getBinding().hasValueSet()) {
|
||||
throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_SLICE_MATCHING__SLICE_MATCHING_BY_VALUE_SET_NOT_DONE));
|
||||
|
|
Loading…
Reference in New Issue