diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java index 4e4fbecce..d258606dc 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java @@ -331,6 +331,7 @@ public class I18nConstants { public static final String REFERENCE_REF_NOTFOUND_BUNDLE = "Reference_REF_NotFound_Bundle"; public static final String REFERENCE_REF_NOTYPE = "Reference_REF_NoType"; public static final String REFERENCE_REF_RESOURCETYPE = "Reference_REF_ResourceType"; + public static final String REFERENCE_REF_SUSPICIOUS = "REFERENCE_REF_SUSPICIOUS"; public static final String REFERENCE_REF_WRONGTARGET = "Reference_REF_WrongTarget"; public static final String REFERENCE_TO__CANNOT_BE_RESOLVED = "reference_to__cannot_be_resolved"; public static final String REFERENCE__REFERS_TO_A__NOT_A_VALUESET = "Reference__refers_to_a__not_a_ValueSet"; diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index 481342e10..a72555b61 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -604,3 +604,4 @@ FHIRPATH_BAD_DATE = Unable to parse Date {0} FHIRPATH_NUMERICAL_ONLY = Error evaluating FHIRPath expression: The function {0} can only be used on integer, decimal or Quantity but found {1} FHIRPATH_DECIMAL_ONLY = Error evaluating FHIRPath expression: The function {0} can only be used on a decimal but found {1} FHIRPATH_FOCUS_PLURAL = Error evaluating FHIRPath expression: focus for {0} has more than one value +REFERENCE_REF_SUSPICIOUS = The syntax of the reference ''{0}'' looks incorrect, and it should be checked diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index 48179bc5e..517b06b11 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -2398,6 +2398,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat // special known URLs that can't be validated but are known to be valid return; } + warning(errors, IssueType.STRUCTURE, element.line(), element.col(), path, !isSuspiciousReference(ref), I18nConstants.REFERENCE_REF_SUSPICIOUS, ref); ResolvedReference we = localResolve(ref, stack, errors, path, (Element) hostContext.getAppContext(), element); String refType; @@ -2439,10 +2440,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } String ft; - if (we != null) + if (we != null) { ft = we.getType(); - else + } else { ft = tryParse(ref); + } if (reference.hasType()) { // R4 onwards... // the type has to match the specified @@ -2596,6 +2598,20 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat } } + private boolean isSuspiciousReference(String url) { + if (!assumeValidRestReferences || url == null || Utilities.isAbsoluteUrl(url)) { + return false; + } + String[] parts = url.split("\\/"); + if (parts.length == 2 && context.getResourceNames().contains(parts[0]) && Utilities.isValidId(parts[1])) { + return false; + } + if (parts.length == 4 && context.getResourceNames().contains(parts[0]) && Utilities.isValidId(parts[1]) && "_history".equals(parts[2]) && Utilities.isValidId(parts[3])) { + return false; + } + return true; + } + private String asListByUrl(Collection list) { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); for (StructureDefinition sd : list) { @@ -4842,7 +4858,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat case 2: return checkResourceType(parts[0]); default: - if (parts[parts.length - 2].equals("_history")) + if (parts[parts.length - 2].equals("_history") && parts.length >= 4) return checkResourceType(parts[parts.length - 4]); else return checkResourceType(parts[parts.length - 2]);