Add IG dependency validator
This commit is contained in:
parent
a9f0b70e30
commit
e731c0c059
|
@ -1080,4 +1080,15 @@ public class I18nConstants {
|
|||
public static final String SD_TYPE_PARAMETER_INVALID_REF = "SD_TYPE_PARAMETER_INVALID_REF";
|
||||
public static final String SD_TYPE_PARAM_NOT_SPECIFIED = "SD_TYPE_PARAM_NOT_SPECIFIED";
|
||||
public static final String SD_TYPE_PARAMETER_ABSTRACT_WARNING = "SD_TYPE_PARAMETER_ABSTRACT_WARNING";
|
||||
public static final String IG_DEPENDENCY_DIRECT = "IG_DEPENDENCY_DIRECT";
|
||||
public static final String IG_DEPENDENCY_INVALID_PACKAGEID = "IG_DEPENDENCY_INVALID_PACKAGEID";
|
||||
public static final String IG_DEPENDENCY_CLASH_PACKAGEID = "IG_DEPENDENCY_CLASH_PACKAGEID";
|
||||
public static final String IG_DEPENDENCY_CLASH_CANONICAL = "IG_DEPENDENCY_CLASH_CANONICAL";
|
||||
public static final String IG_DEPENDENCY_NO_PACKAGE = "IG_DEPENDENCY_NO_PACKAGE";
|
||||
public static final String IG_DEPENDENCY_NO_VERSION = "IG_DEPENDENCY_NO_VERSION";
|
||||
public static final String IG_DEPENDENCY_INVALID_PACKAGE_VERSION = "IG_DEPENDENCY_INVALID_PACKAGE_VERSION";
|
||||
public static final String IG_DEPENDENCY_VERSION_ERROR = "IG_DEPENDENCY_VERSION_ERROR";
|
||||
public static final String IG_DEPENDENCY_VERSION_WARNING = "IG_DEPENDENCY_VERSION_WARNING";
|
||||
public static final String IG_DEPENDENCY_EXCEPTION = "IG_DEPENDENCY_EXCEPTION";
|
||||
public static final String IG_DEPENDENCY_PACKAGE_UNKNOWN = "IG_DEPENDENCY_PACKAGE_UNKNOWN";
|
||||
}
|
||||
|
|
|
@ -1108,3 +1108,14 @@ SD_TYPE_PARAMETER_INVALID = The type definition ''{2}'' has a type parameter ''{
|
|||
SD_TYPE_PARAMETER_INVALID_REF = The type ''{0}'' is a reference to ''{1}'' which has a type parameter ''{2}'' with a base type of {3} but the type parameter provided is ''{4}'' which is not the right type
|
||||
SD_TYPE_PARAM_NOT_SPECIFIED = The type ''{0}'' at {3} is a reference to ''{1}'' which needs a type parameter ''{2}'' but a type parameter is not provided for ''{2}''
|
||||
SD_TYPE_PARAMETER_ABSTRACT_WARNING = The type ''{0}'' at {3} refers to the abstract type ''{1}'' but the context is not an abstract type - this is usually an error
|
||||
IG_DEPENDENCY_DIRECT = The URL should refer directly to the ImplementationGuide resource (e.g. include ''/ImplementationGuide/'')
|
||||
PACKAGE_REGEX = The packageId {0} is not valid
|
||||
IG_DEPENDENCY_CLASH_PACKAGEID = The canonical URL {0} points to the package {1} which is inconsistent with the stated packageId of {2}
|
||||
IG_DEPENDENCY_CLASH_CANONICAL = The packageId {0} points to the canonical {1} which is inconsistent with the stated canonical of {2}
|
||||
IG_DEPENDENCY_NO_PACKAGE = No NPM package id could be determined so the version consistency can't be checked
|
||||
IG_DEPENDENCY_NO_VERSION = No version was specified for the package so the version consistency can't be checked
|
||||
IG_DEPENDENCY_INVALID_PACKAGE_VERSION = The version {0} is not a valid NPM package version
|
||||
IG_DEPENDENCY_PACKAGE_UNKNOWN = The package {0} could not be found so the version consistency can't be checked
|
||||
IG_DEPENDENCY_VERSION_ERROR = The ImplementationGuide is based on FHIR version {0} but package {1} is based on FHIR version {2}. Use the package {3} instead
|
||||
IG_DEPENDENCY_VERSION_WARNING = The ImplementationGuide is based on FHIR version {0} but package {1} is based on FHIR version {2}. In general, this version mismatch should be avoided - some tools will try to make this work with variable degrees of success, but others will not even try
|
||||
IG_DEPENDENCY_EXCEPTION = Exception checking package version consistency: {0}
|
||||
|
|
|
@ -219,6 +219,7 @@ import org.hl7.fhir.validation.instance.InstanceValidator.BindingContext;
|
|||
import org.hl7.fhir.validation.instance.type.BundleValidator;
|
||||
import org.hl7.fhir.validation.instance.type.CodeSystemValidator;
|
||||
import org.hl7.fhir.validation.instance.type.ConceptMapValidator;
|
||||
import org.hl7.fhir.validation.instance.type.ImplementationGuideValidator;
|
||||
import org.hl7.fhir.validation.instance.type.MeasureValidator;
|
||||
import org.hl7.fhir.validation.instance.type.ObservationValidator;
|
||||
import org.hl7.fhir.validation.instance.type.QuestionnaireValidator;
|
||||
|
@ -5771,6 +5772,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return new StructureMapValidator(this, fpe, profileUtilities).validateStructureMap(valContext, errors, element, stack) && ok;
|
||||
} else if (element.getType().equals("ValueSet")) {
|
||||
return new ValueSetValidator(this).validateValueSet(valContext, errors, element, stack) && ok;
|
||||
} else if (element.getType().equals("ImplementationGuide")) {
|
||||
return new ImplementationGuideValidator(this.context, xverManager, debug).validateImplementationGuide(valContext, errors, element, stack) && ok;
|
||||
} else if ("http://hl7.org/fhir/uv/sql-on-fhir/StructureDefinition/ViewDefinition".equals(element.getProperty().getStructure().getUrl())) {
|
||||
if (element.getNativeObject() != null && element.getNativeObject() instanceof JsonObject) {
|
||||
JsonObject json = (JsonObject) element.getNativeObject();
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
package org.hl7.fhir.validation.instance.type;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.elementmodel.Element;
|
||||
import org.hl7.fhir.r5.elementmodel.ObjectConverter;
|
||||
import org.hl7.fhir.r5.fhirpath.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.DateType;
|
||||
import org.hl7.fhir.r5.model.IntegerType;
|
||||
import org.hl7.fhir.r5.model.Questionnaire;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemAnswerOptionComponent;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent;
|
||||
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemType;
|
||||
import org.hl7.fhir.r5.model.Reference;
|
||||
import org.hl7.fhir.r5.model.StringType;
|
||||
import org.hl7.fhir.r5.model.TimeType;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier.ValidationContextResourceProxy;
|
||||
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
|
||||
import org.hl7.fhir.utilities.npm.NpmPackage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||
import org.hl7.fhir.utilities.validation.ValidationOptions;
|
||||
import org.hl7.fhir.validation.BaseValidator;
|
||||
import org.hl7.fhir.validation.cli.utils.QuestionnaireMode;
|
||||
import org.hl7.fhir.validation.instance.utils.EnableWhenEvaluator;
|
||||
import org.hl7.fhir.validation.instance.utils.NodeStack;
|
||||
import org.hl7.fhir.validation.instance.utils.ValidationContext;
|
||||
import org.hl7.fhir.validation.instance.utils.EnableWhenEvaluator.QStack;
|
||||
|
||||
import ca.uhn.fhir.util.ObjectUtil;
|
||||
|
||||
public class ImplementationGuideValidator extends BaseValidator {
|
||||
|
||||
public ImplementationGuideValidator(IWorkerContext context, XVerExtensionManager xverManager, boolean debug) {
|
||||
super(context, xverManager, debug);
|
||||
}
|
||||
|
||||
public boolean validateImplementationGuide(ValidationContext valContext, List<ValidationMessage> errors, Element ig, NodeStack stack) {
|
||||
boolean ok = true;
|
||||
String fver = ig.getNamedChildValue("fhirVersion");
|
||||
|
||||
List<Element> dependencies = ig.getChildrenByName("dependsOn");
|
||||
int i = 0;
|
||||
for (Element dependency : dependencies) {
|
||||
ok = checkDependency(errors, ig, stack.push(dependency, i, null, null), dependency, fver) && ok;
|
||||
i++;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean checkDependency(List<ValidationMessage> errors, Element ig, NodeStack stack, Element dependency, String fver) {
|
||||
boolean ok = true;
|
||||
String url = dependency.getNamedChildValue("url");
|
||||
String packageId = dependency.getNamedChildValue("packageId");
|
||||
String version = dependency.getNamedChildValue("version");
|
||||
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), url == null || url.contains("/ImplementationGuide/"), I18nConstants.IG_DEPENDENCY_DIRECT, url) && ok;
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), packageId == null || packageId.matches(FilesystemPackageCacheManager.PACKAGE_REGEX), I18nConstants.IG_DEPENDENCY_INVALID_PACKAGEID, packageId) && ok;
|
||||
|
||||
try {
|
||||
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager.Builder().build();
|
||||
if (url != null && packageId != null) {
|
||||
String pid = pcm.getPackageId(url);
|
||||
String canonical = pcm.getPackageUrl(packageId);
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), pid == null || pid.equals(packageId), I18nConstants.IG_DEPENDENCY_CLASH_PACKAGEID, url, pid, packageId) && ok;
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), canonical == null || canonical.equals(url), I18nConstants.IG_DEPENDENCY_CLASH_CANONICAL, packageId, canonical, url) && ok;
|
||||
}
|
||||
if (packageId == null && ok) {
|
||||
packageId = pcm.getPackageId(url);
|
||||
}
|
||||
if (ok && warning(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), packageId != null, I18nConstants.IG_DEPENDENCY_NO_PACKAGE) &&
|
||||
warning(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), version != null, I18nConstants.IG_DEPENDENCY_NO_VERSION)) {
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), (packageId+"#"+version).matches(FilesystemPackageCacheManager.PACKAGE_VERSION_REGEX), I18nConstants.IG_DEPENDENCY_INVALID_PACKAGE_VERSION, version) && ok;
|
||||
NpmPackage npm = pcm.loadPackage(packageId, version);
|
||||
if (warning(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), npm != null, I18nConstants.IG_DEPENDENCY_PACKAGE_UNKNOWN, packageId+"#"+version)) {
|
||||
String pver = npm.fhirVersion();
|
||||
if (!VersionUtilities.versionsMatch(pver, fver)) {
|
||||
if ("hl7.fhir.uv.extensions".equals(packageId)) {
|
||||
ok = rule(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), false, I18nConstants.IG_DEPENDENCY_VERSION_ERROR, fver, packageId+"#"+version, pver,
|
||||
"hl7.fhir.uv.extensions."+VersionUtilities.getNameForVersion(fver).toLowerCase()) && ok;
|
||||
} else {
|
||||
warning(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), false, I18nConstants.IG_DEPENDENCY_VERSION_WARNING, fver, packageId+"#"+version, pver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
warning(errors, "2024-06-13", IssueType.BUSINESSRULE, dependency.line(), dependency.col(), stack.getLiteralPath(), version != null, I18nConstants.IG_DEPENDENCY_EXCEPTION, e.getMessage());
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue