Merge pull request #1876 from hapifhir/2025-01-gg-deprecated-note

2025 01 gg deprecated note
This commit is contained in:
Grahame Grieve 2025-01-10 18:22:26 +11:00 committed by GitHub
commit 2d5a8e06e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 105 additions and 17 deletions

View File

@ -366,6 +366,16 @@ Modifier extensions SHALL NOT change the meaning of any elements on Resource or
super.copyNewExtensions(src, urls);
}
public Base getExtensionValue(String... theUrls) {
for (Extension next : getModifierExtension()) {
if (Utilities.existsInList(next.getUrl(), theUrls)) {
return next.getValue();
}
}
return super.getExtensionValue(theUrls);
}
// end addition
}

View File

@ -440,6 +440,15 @@ public abstract class Element extends Base implements IBaseHasExtensions, IBaseE
return false;
}
public Base getExtensionValue(String... theUrls) {
for (Extension next : getExtension()) {
if (Utilities.existsInList(next.getUrl(), theUrls)) {
return next.getValue();
}
}
return null;
}
/**
* Returns an true if this element has an extension that matchs the given URL.

View File

@ -34,6 +34,7 @@ import org.hl7.fhir.utilities.FhirPublication;
import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.MarkDownProcessor.Dialect;
import org.hl7.fhir.utilities.StandardsStatus;
import org.hl7.fhir.utilities.StringPair;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.i18n.RenderingI18nContext;
import org.hl7.fhir.utilities.validation.ValidationOptions;
@ -295,7 +296,7 @@ public class RenderingContext extends RenderingI18nContext {
private List<String> files = new ArrayList<String>(); // files created as by-products in destDir
private Map<KnownLinkType, String> links = new HashMap<>();
private Map<String, String> namedLinks = new HashMap<>();
private Map<String, StringPair> namedLinks = new HashMap<>();
private boolean addName = false;
private Map<String, String> typeMap = new HashMap<>(); // type aliases that can be resolved in Markdown type links (mainly for cross-version usage)
private int base64Limit = 1024;
@ -781,7 +782,7 @@ public class RenderingContext extends RenderingI18nContext {
return this;
}
public Map<String, String> getNamedLinks() {
public Map<String, StringPair> getNamedLinks() {
return namedLinks;
}

View File

@ -1105,5 +1105,14 @@ public class CodeSystemUtilities extends TerminologyUtilities {
public static boolean isExemptFromMultipleVersionChecking(String url) {
return Utilities.existsInList(url, "http://snomed.info/sct", "http://loinc.org");
}
public static PropertyComponent getPropertyByUri(CodeSystem cs, String uri) {
for (PropertyComponent t : cs.getProperty()) {
if (uri.equals(t.getUri())) {
return t;
}
}
return null;
}
}

View File

@ -570,8 +570,14 @@ public class ToolingExtensions {
return ((BooleanType) ex.getValue()).getValue();
}
public static boolean readBoolExtension(DomainResource c, String uri) {
Extension ex = ExtensionHelper.getExtension(c, uri);
public static boolean readBoolExtension(DomainResource c, String... uris) {
Extension ex = null;
for (String uri : uris) {
ex = ExtensionHelper.getExtension(c, uri);
if (ex != null) {
break;
}
}
if (ex == null)
return false;
if (!(ex.getValue() instanceof BooleanType))
@ -785,6 +791,17 @@ public class ToolingExtensions {
element.getExtension().add(new Extension(uri).setValue(new CodeType(value)));
}
public static void setMarkdownExtension(DomainResource resource, String uri, String value) {
if (Utilities.noString(value))
return;
Extension ext = getExtension(resource, uri);
if (ext != null)
ext.setValue(new MarkdownType(value));
else
resource.getExtension().add(new Extension(uri).setValue(new MarkdownType(value)));
}
public static void setIntegerExtension(DomainResource resource, String uri, int value) {
Extension ext = getExtension(resource, uri);
if (ext != null)

View File

@ -41,6 +41,7 @@ import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.commonmark.renderer.text.TextContentRenderer;
import com.github.rjeschke.txtmark.Configuration;
import com.github.rjeschke.txtmark.Processor;
@ -278,4 +279,15 @@ public class MarkDownProcessor {
return b.toString();
}
public static String markdownToPlainText(String source) {
if (source == null) {
return "";
}
Set<Extension> extensions = Collections.singleton(TablesExtension.create());
Parser parser = Parser.builder().extensions(extensions).build();
Node document = parser.parse(source);
TextContentRenderer renderer = TextContentRenderer.builder().stripNewlines(true).extensions(extensions).build();
String text = renderer.render(document);
return text;
}
}

View File

@ -674,6 +674,13 @@ public class Utilities {
return PathBuilder.getPathBuilder().buildPath(a);
}
public static String forcePath(String... args) throws IOException {
String path = path(args);
String folder = Utilities.getDirectoryForFile(path);
Utilities.createDirectory(folder);
return path;
}
/**
* Composes a path string using by concatenating the passed arguments.
*

View File

@ -413,6 +413,7 @@ public class I18nConstants {
public static final String MEASURE_SHAREABLE_MISSING_HL7 = "MEASURE_SHAREABLE_MISSING_HL7";
public static final String META_RES_SECURITY_DUPLICATE = "Meta_RES_Security_Duplicate";
public static final String MSG_DEPENDS_ON_DEPRECATED = "MSG_DEPENDS_ON_DEPRECATED";
public static final String MSG_DEPENDS_ON_DEPRECATED_NOTE = "MSG_DEPENDS_ON_DEPRECATED_NOTE";
public static final String MSG_DEPENDS_ON_DRAFT = "MSG_DEPENDS_ON_DRAFT";
public static final String MSG_DEPENDS_ON_EXPERIMENTAL = "MSG_DEPENDS_ON_EXPERIMENTAL";
public static final String MSG_DEPENDS_ON_EXTENSION = "MSG_DEPENDS_ON_EXTENSION";

View File

@ -416,6 +416,7 @@ MEASURE_SHAREABLE_EXTRA_MISSING_HL7 = Measures published by HL7 SHALL conform to
MEASURE_SHAREABLE_MISSING = Published measures SHOULD conform to the ShareableMeasure profile, which says that the element Measure.{0} is mandatory, but it is not present
MEASURE_SHAREABLE_MISSING_HL7 = Measures published by HL7 SHALL conform to the ShareableMeasure profile, which says that the element Measure.{0} is mandatory, but it is not present
MSG_DEPENDS_ON_DEPRECATED = The {0} {1} is deprecated
MSG_DEPENDS_ON_DEPRECATED_NOTE = The {0} {1} is deprecated with the note {2}
MSG_DEPENDS_ON_DRAFT = The {0} {1} is a draft resource
MSG_DEPENDS_ON_EXPERIMENTAL = The {0} {1} is an experimental resource
MSG_DEPENDS_ON_EXTENSION = extension
@ -1210,7 +1211,7 @@ VALUESET_INCLUDE_WRONG_VS_MANY = The system ''{0}'' is actually a value set, whi
CODESYSTEM_PROPERTY_URI_UNKNOWN = The property uri ''{0}'' is not known, so the property values can not be validated fully
CODESYSTEM_PROPERTY_URI_UNKNOWN_TYPE = The property uri ''{0}'' is not known, so the property values can not be validated fully; unless specified elsewhere, codes will be treated as internal references
CODESYSTEM_PROPERTY_URI_UNKNOWN_BASE = The base property uri ''{0}'' is not known for the property ''{1}'', so the property values can not be validated fully
CODESYSTEM_PROPERTY_URI_INVALID = The uri ''{3}'' for the property ''{4}'' implies the code ''{0}'' exists in the CodeSystem {2} for {1} but it does not exist
CODESYSTEM_PROPERTY_URI_INVALID = The uri ''{3}'' for the property ''{4}'' implies a property with that URI exists in the CodeSystem {2} for {1}, or the code ''{0}'' does, but neither were found
CODESYSTEM_PROPERTY_CODE_DEFAULT_WARNING = The type of property ''{0}'' is ''code'', but no ValueSet information was found, so the codes will be validated as internal codes
CODESYSTEM_PROPERTY_VALUESET_NOT_FOUND = The ValueSet {0} is unknown, so the property codes cannot be validated
CODESYSTEM_PROPERTY_BAD_INTERNAL_REFERENCE = The code ''{0}'' is not a valid code in this code system

View File

@ -58,6 +58,7 @@ import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Constants;
import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.UsageContext;
import org.hl7.fhir.r5.model.ValueSet;
@ -77,6 +78,7 @@ import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.FhirPublication;
import org.hl7.fhir.utilities.MarkDownProcessor;
import org.hl7.fhir.utilities.StandardsStatus;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
@ -1563,10 +1565,15 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
String vurl = ex.getVersionedUrl();
StandardsStatus standardsStatus = ToolingExtensions.getStandardsStatus(ex);
Extension ext = ex.getExtensionByUrl(ToolingExtensions.EXT_STANDARDS_STATUS);
ext = ext == null || !ext.hasValue() ? null : ext.getValue().getExtensionByUrl(ToolingExtensions.EXT_STANDARDS_STATUS_REASON);
String note = ext == null || !ext.hasValue() ? null : MarkDownProcessor.markdownToPlainText(ext.getValue().primitiveValue());
if (standardsStatus == StandardsStatus.DEPRECATED) {
if (!statusWarnings.contains(vurl+":DEPRECATED")) {
statusWarnings.add(vurl+":DEPRECATED");
hint(errors, "2023-08-10", IssueType.BUSINESSRULE, element.line(), element.col(), path, false, I18nConstants.MSG_DEPENDS_ON_DEPRECATED, type, vurl);
hint(errors, "2023-08-10", IssueType.BUSINESSRULE, element.line(), element.col(), path, false,
Utilities.noString(note) ? I18nConstants.MSG_DEPENDS_ON_DEPRECATED : I18nConstants.MSG_DEPENDS_ON_DEPRECATED_NOTE, type, vurl, note);
}
} else if (standardsStatus == StandardsStatus.WITHDRAWN) {
if (!statusWarnings.contains(vurl+":WITHDRAWN")) {

View File

@ -7224,7 +7224,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
}
if (!ToolingExtensions.readBoolExtension(profile, "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-no-order")) {
if (!ToolingExtensions.readBoolExtension(profile, "http://hl7.org/fhir/StructureDefinition/structuredefinition-xml-no-order", "http://hl7.org/fhir/tools/StructureDefinition/xml-no-order")) {
boolean bok = (ei.definition == null) || (ei.index >= last) || isXmlAttr || ei.getElement().isIgnorePropertyOrder();
bh.see(rule(errors, NO_RULE_DATE, IssueType.INVALID, ei.line(), ei.col(), ei.getPath(), bok, I18nConstants.VALIDATION_VAL_PROFILE_OUTOFORDER, profile.getVersionedUrl(), ei.getName(), lastei == null ? "(null)" : lastei.getName()));
}

View File

@ -53,7 +53,7 @@ public class RulesDrivenPolicyAdvisor extends BasePolicyAdvisorForFullValidation
public boolean matches(@Nonnull String mid, @Nonnull String path, String[] p) {
if (regex) {
return stringMatches(id, mid) && regexMatches(path, path);
return stringMatches(id, mid) && regexMatches(this.path, path);
} else {
return stringMatches(id, mid) && pathMatches(pathSegments, p);
}
@ -97,7 +97,7 @@ public class RulesDrivenPolicyAdvisor extends BasePolicyAdvisorForFullValidation
if (specifier == null) {
return true;
} else if (specifier.endsWith("*")) {
return specifier.substring(0, specifier.length()-1).equalsIgnoreCase(actual.substring(0, specifier.length()-1));
return specifier.substring(0, specifier.length()-1).equalsIgnoreCase(actual.substring(0, Integer.min(specifier.length()-1, actual.length())));
} else {
return specifier.equalsIgnoreCase(actual);
}

View File

@ -13,6 +13,7 @@ import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.r5.model.CodeSystem.ConceptPropertyComponent;
import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
@ -261,6 +262,18 @@ public class CodeSystemValidator extends BaseValidator {
CodeSystem pcs = context.findTxResource(CodeSystem.class, base);
if (pcs == null) {
warning(errors, "2025-01-09", IssueType.NOTFOUND, cs.line(), cs.col(), stack.getLiteralPath(), false, I18nConstants.CODESYSTEM_PROPERTY_URI_UNKNOWN_BASE, base, code);
} else {
PropertyComponent cp = CodeSystemUtilities.getPropertyByUri(pcs, uri);
if (cp != null) {
foundPropDefn = true;
if ("code".equals(type)) {
if (cp.hasExtension("http://hl7.org/fhir/StructureDefinition/codesystem-property-valueset", "http://hl7.org/fhir/6.0/StructureDefinition/extension-CodeSystem.property.valueSet")) {
ruleFromUri = CodeValidationRule.VS_ERROR;
valuesetFromUri = cp.getExtensionValue("http://hl7.org/fhir/StructureDefinition/codesystem-property-valueset", "http://hl7.org/fhir/6.0/StructureDefinition/extension-CodeSystem.property.valueSet").primitiveValue();
} else {
ruleFromUri = CodeValidationRule.INTERNAL_CODE_WARNING;
}
}
} else {
ConceptDefinitionComponent cc = CodeSystemUtilities.findCode(pcs.getConcept(), pcode);
if (warning(errors, "2025-01-09", IssueType.INVALID, cs.line(), cs.col(), stack.getLiteralPath(), cc != null, I18nConstants.CODESYSTEM_PROPERTY_URI_INVALID, pcode, base, pcs.present(), uri, code)) {
@ -280,6 +293,7 @@ public class CodeSystemValidator extends BaseValidator {
}
}
}
}
} else {
if ("code".equals(type)) {
warning(errors, "2025-01-09", IssueType.NOTFOUND, cs.line(), cs.col(), stack.getLiteralPath(), false, I18nConstants.CODESYSTEM_PROPERTY_URI_UNKNOWN_TYPE, uri);

View File

@ -23,7 +23,7 @@
<commons_io_version>2.17.0</commons_io_version>
<guava_version>32.0.1-jre</guava_version>
<hapi_fhir_version>6.4.1</hapi_fhir_version>
<validator_test_case_version>1.7.5</validator_test_case_version>
<validator_test_case_version>1.7.6-SNAPSHOT</validator_test_case_version>
<jackson_version>2.17.0</jackson_version>
<junit_jupiter_version>5.9.2</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>