Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ internal static OperationOutcome ValidateChildConstraints(this Validator validat
validator.Trace(outcome, "Start validation of inlined child constraints for '{0}'".FormatWith(definition.Path), Issue.PROCESSING_PROGRESS, instance);

// validate the type on the parent of children. If this is a reference type, it will follow that reference as well
outcome.Add(validator.ValidateTargetProfiles(definition.Current, instance));
outcome.Add(validator.ValidateTypeReferences(definition.Current.Type, instance, validateProfiles: false));

var matchResult = ChildNameMatcher.Match(definition, instance);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,62 +79,41 @@ internal static OperationOutcome ValidateType(this Validator validator, ElementD


internal static OperationOutcome ValidateTypeReferences(this Validator validator,
IEnumerable<ElementDefinition.TypeRefComponent> typeRefs, ScopedNode instance)
IEnumerable<ElementDefinition.TypeRefComponent> typeRefs, ScopedNode instance, bool validateProfiles = true)
{
//TODO: It's more efficient to do the non-reference types FIRST, since ANY match would be ok,
//and validating non-references is cheaper
//TODO: For each choice, we will currently try to resolve the reference. If it fails, you'll get multiple errors and probably
//better separate the fetching of the instance from the validation, so we do not run the rest of the validation (multiple times!)
//when a reference cannot be resolved. (this happens in a choice type where there are multiple references with multiple profiles)

IEnumerable<Func<OperationOutcome>> validations = typeRefs.Select(tr => createValidatorForTypeRef(validator, instance, tr));
IEnumerable<Func<OperationOutcome>> validations = typeRefs.Select(tr => createValidatorForTypeRef(validator, instance, tr, validateProfiles));
return validator.Combine(BatchValidationMode.Any, instance, validations);
}

private static Func<OperationOutcome> createValidatorForTypeRef(Validator validator, ScopedNode instance, ElementDefinition.TypeRefComponent tr)
private static Func<OperationOutcome> createValidatorForTypeRef(Validator validator, ScopedNode instance, ElementDefinition.TypeRefComponent tr,
bool validateProfiles)
{
return validate;

OperationOutcome validate()
{
// First, call Validate() for the current element (the reference itself) against the profile
var result = validator.Validate(instance, tr.GetDeclaredProfiles(), statedCanonicals: null, statedProfiles: null);
OperationOutcome result = new();

result.Add(validateTargetProfiles(validator, instance, tr));
if (validateProfiles)
{
// First, call Validate() for the current element (the reference itself) against the profile
result.Add(validator.Validate(instance, tr.GetDeclaredProfiles(), statedCanonicals: null, statedProfiles: null));
}

return result;
}
}
// If this is a reference, also validate the reference against the targetProfile
if (ModelInfo.FhirTypeNameToFhirType(tr.Code) == FHIRAllTypes.Reference)
result.Add(validator.ValidateResourceReference(instance, tr));

internal static OperationOutcome ValidateTargetProfiles(this Validator validator, ElementDefinition definition, ScopedNode instance)
{
var typeRefs = definition.Type.Where(tr => tr.Code != null);
IEnumerable<Func<OperationOutcome>> validations = typeRefs.Select(tr => createValidatorForTargetProfiles(validator, instance, tr));
return validator.Combine(BatchValidationMode.Any, instance, validations);
}

private static Func<OperationOutcome> createValidatorForTargetProfiles(Validator validator, ScopedNode instance, ElementDefinition.TypeRefComponent tr)
{
return validate;

OperationOutcome validate()
{
var result = validateTargetProfiles(validator, instance, tr);
return result;
}
}

private static OperationOutcome validateTargetProfiles(Validator validator, ScopedNode instance, ElementDefinition.TypeRefComponent tr)
{
var result = new OperationOutcome();

// If this is a reference, also validate the reference against the targetProfile
if (ModelInfo.FhirTypeNameToFhirType(tr.Code) == FHIRAllTypes.Reference)
result.Add(validator.ValidateResourceReference(instance, tr));

return result;
}

internal static OperationOutcome ValidateResourceReference(this Validator validator, ScopedNode instance, ElementDefinition.TypeRefComponent typeRef)
{
var outcome = new OperationOutcome();
Expand Down Expand Up @@ -240,4 +219,4 @@ private static ITypedElement resolveReference(this Validator validator, ScopedNo
return result;
}
}
}
}