Add support for -advisor-file, and -clear-tx-cache
This commit is contained in:
parent
9809800d8d
commit
56965820ea
|
@ -80,7 +80,7 @@ public interface IResourceValidator {
|
|||
IResourceValidator setFetcher(IValidatorResourceFetcher value);
|
||||
|
||||
IValidationPolicyAdvisor getPolicyAdvisor();
|
||||
IResourceValidator setPolicyAdvisor(IValidationPolicyAdvisor advisor);
|
||||
void setPolicyAdvisor(IValidationPolicyAdvisor advisor);
|
||||
|
||||
IValidationProfileUsageTracker getTracker();
|
||||
IResourceValidator setTracker(IValidationProfileUsageTracker value);
|
||||
|
|
|
@ -16,6 +16,21 @@ import org.hl7.fhir.r5.utils.validation.constants.BindingKind;
|
|||
|
||||
public interface IValidationPolicyAdvisor {
|
||||
|
||||
/**
|
||||
* Internal use, for chaining advisors
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
ReferenceValidationPolicy getReferencePolicy();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param path - the current path of the element
|
||||
* @param messageId - the message id (from messages.properties)
|
||||
* @return true if the validator should ignore the message
|
||||
*/
|
||||
boolean suppressMessageId(String path, String messageId);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param validator
|
||||
|
@ -169,5 +184,6 @@ public interface IValidationPolicyAdvisor {
|
|||
boolean valid,
|
||||
IMessagingServices msgServices,
|
||||
List<ValidationMessage> messages);
|
||||
|
||||
|
||||
}
|
|
@ -69,9 +69,11 @@ import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
|||
import org.hl7.fhir.r5.utils.XVerExtensionManager.XVerExtensionStatus;
|
||||
import org.hl7.fhir.r5.utils.validation.IMessagingServices;
|
||||
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
|
||||
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier.IValidationContextResourceLoader;
|
||||
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.StandardsStatus;
|
||||
|
@ -85,6 +87,7 @@ import org.hl7.fhir.utilities.validation.ValidationMessage.IssueType;
|
|||
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
import org.hl7.fhir.validation.cli.utils.ValidationLevel;
|
||||
import org.hl7.fhir.validation.instance.advisor.BasePolicyAdvisorForFullValidation;
|
||||
import org.hl7.fhir.validation.instance.utils.IndexedElement;
|
||||
import org.hl7.fhir.validation.instance.utils.NodeStack;
|
||||
|
||||
|
@ -165,25 +168,31 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
protected final String BUNDLE = "Bundle";
|
||||
protected final String LAST_UPDATED = "lastUpdated";
|
||||
|
||||
protected String sessionId;
|
||||
protected BaseValidator parent;
|
||||
protected Source source;
|
||||
protected IWorkerContext context;
|
||||
protected ValidationTimeTracker timeTracker = new ValidationTimeTracker();
|
||||
protected XVerExtensionManager xverManager;
|
||||
protected List<TrackedLocationRelatedMessage> trackedMessages = new ArrayList<>();
|
||||
protected List<ValidationMessage> messagesToRemove = new ArrayList<>();
|
||||
protected ValidationLevel level = ValidationLevel.HINTS;
|
||||
protected Coding jurisdiction;
|
||||
protected boolean allowExamples;
|
||||
protected boolean forPublication;
|
||||
protected boolean debug;
|
||||
protected boolean warnOnDraftOrExperimental;
|
||||
protected Set<String> statusWarnings = new HashSet<>();
|
||||
protected BestPracticeWarningLevel bpWarnings = BestPracticeWarningLevel.Warning;
|
||||
protected String sessionId = Utilities.makeUuidLC();
|
||||
protected List<UsageContext> usageContexts = new ArrayList<UsageContext>();
|
||||
protected ValidationOptions baseOptions = new ValidationOptions(FhirPublication.R5);
|
||||
protected IValidatorResourceFetcher fetcher;
|
||||
protected IValidationPolicyAdvisor policyAdvisor;
|
||||
|
||||
// these two related to removing warnings on extensible bindings in structures that have derivatives that replace their bindings
|
||||
protected List<TrackedLocationRelatedMessage> trackedMessages = new ArrayList<>();
|
||||
protected List<ValidationMessage> messagesToRemove = new ArrayList<>();
|
||||
|
||||
// don't repeatedly raise the same warnings all the time
|
||||
protected Set<String> statusWarnings = new HashSet<>();
|
||||
|
||||
protected Source source; // @configuration
|
||||
protected ValidationLevel level = ValidationLevel.HINTS; // @configuration
|
||||
protected Coding jurisdiction; // @configuration
|
||||
protected boolean allowExamples; // @configuration
|
||||
protected boolean forPublication; // @configuration
|
||||
protected boolean debug; // @configuration
|
||||
protected boolean warnOnDraftOrExperimental; // @configuration
|
||||
protected BestPracticeWarningLevel bpWarnings = BestPracticeWarningLevel.Warning; // @configuration
|
||||
protected List<UsageContext> usageContexts = new ArrayList<UsageContext>(); // @configuration
|
||||
protected ValidationOptions baseOptions = new ValidationOptions(FhirPublication.R5); // @configuration
|
||||
|
||||
public BaseValidator(IWorkerContext context, XVerExtensionManager xverManager, boolean debug) {
|
||||
super();
|
||||
|
@ -193,6 +202,8 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
this.xverManager = new XVerExtensionManager(context);
|
||||
}
|
||||
this.debug = debug;
|
||||
sessionId = Utilities.makeUuidLC();
|
||||
policyAdvisor = new BasePolicyAdvisorForFullValidation(ReferenceValidationPolicy.CHECK_VALID);
|
||||
urlRegex = Constants.URI_REGEX_XVER.replace("$$", CommaSeparatedStringBuilder.join("|", context.getResourceNames()));
|
||||
}
|
||||
|
||||
|
@ -217,6 +228,8 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
this.usageContexts.addAll(parent.usageContexts);
|
||||
this.baseOptions = parent.baseOptions;
|
||||
this.fetcher = parent.fetcher;
|
||||
this.sessionId = parent.sessionId;
|
||||
this.policyAdvisor = parent.policyAdvisor;
|
||||
}
|
||||
|
||||
private boolean doingLevel(IssueSeverity error) {
|
||||
|
@ -261,75 +274,22 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
|
||||
protected String urlRegex;
|
||||
|
||||
/**
|
||||
* Test a rule and add a {@link IssueSeverity#FATAL} validation message if the validation fails
|
||||
*
|
||||
* @param thePass
|
||||
* Set this parameter to <code>false</code> if the validation does not pass
|
||||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
@Deprecated
|
||||
protected boolean fail(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg) {
|
||||
if (!thePass && doingErrors()) {
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, msg, IssueSeverity.FATAL, null);
|
||||
private boolean suppressMsg(String path, String theMessage) {
|
||||
if (policyAdvisor == null) {
|
||||
return false;
|
||||
} else {
|
||||
return policyAdvisor.suppressMessageId(path, theMessage);
|
||||
}
|
||||
return thePass;
|
||||
}
|
||||
|
||||
protected boolean fail(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
if (!thePass && doingErrors() && !suppressMsg(path, theMessage)) {
|
||||
String msg = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, msg, IssueSeverity.FATAL, theMessage);
|
||||
}
|
||||
return thePass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a rule and add a {@link IssueSeverity#FATAL} validation message if the validation fails
|
||||
*
|
||||
* @param thePass
|
||||
* Set this parameter to <code>false</code> if the validation does not pass
|
||||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
@Deprecated
|
||||
protected boolean fail(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String msg) {
|
||||
if (!thePass && doingErrors()) {
|
||||
String path = toPath(pathParts);
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, msg, IssueSeverity.FATAL, null);
|
||||
}
|
||||
return thePass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a rule and add a {@link IssueSeverity#FATAL} validation message if the validation fails
|
||||
*
|
||||
* @param thePass
|
||||
* Set this parameter to <code>false</code> if the validation does not pass
|
||||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
@Deprecated
|
||||
protected boolean fail(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
String path = toPath(pathParts);
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, context.formatMessage(theMessage, theMessageArguments), IssueSeverity.FATAL, theMessage);
|
||||
}
|
||||
return thePass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a rule and add a {@link IssueSeverity#FATAL} validation message if the validation fails
|
||||
*
|
||||
* @param thePass
|
||||
* Set this parameter to <code>false</code> if the validation does not pass
|
||||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
@Deprecated
|
||||
protected boolean fail(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg) {
|
||||
if (!thePass && doingErrors()) {
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, msg, IssueSeverity.FATAL, null);
|
||||
}
|
||||
return thePass;
|
||||
}
|
||||
//TODO: i18n
|
||||
protected boolean grammarWord(String w) {
|
||||
return w.equals("and") || w.equals("or") || w.equals("a") || w.equals("the") || w.equals("for") || w.equals("this") || w.equals("that") || w.equals("of");
|
||||
|
@ -343,7 +303,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean hint(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg) {
|
||||
if (!thePass && doingHints()) {
|
||||
if (!thePass && doingHints() && !suppressMsg(path, msg)) {
|
||||
String message = context.formatMessage(msg);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, msg);
|
||||
}
|
||||
|
@ -358,7 +318,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean hintInv(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, String invId) {
|
||||
if (!thePass && doingHints()) {
|
||||
if (!thePass && doingHints() && !suppressMsg(path, invId)) {
|
||||
String message = context.formatMessage(msg);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, msg).setInvId(invId);
|
||||
}
|
||||
|
@ -397,7 +357,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean hint(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingHints()) {
|
||||
if (!thePass && doingHints() && !suppressMsg(path, theMessage)) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage);
|
||||
}
|
||||
|
@ -405,7 +365,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean hintPlural(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, int num, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingHints()) {
|
||||
if (!thePass && doingHints() && !suppressMsg(path, theMessage)) {
|
||||
String message = context.formatMessagePlural(num, theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, theMessage);
|
||||
}
|
||||
|
@ -418,7 +378,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean txHint(List<ValidationMessage> errors, String ruleDate, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingHints()) {
|
||||
if (!thePass && doingHints() && !suppressMsg(path, theMessage)) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.INFORMATION, Source.TerminologyEngine, theMessage).setTxLink(txLink);
|
||||
}
|
||||
|
@ -433,7 +393,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean hint(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingHints()) {
|
||||
if (!thePass && doingHints() && !suppressMsg(CommaSeparatedStringBuilder.join(".", pathParts), theMessage)) {
|
||||
String path = toPath(pathParts);
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.INFORMATION, theMessage);
|
||||
|
@ -449,7 +409,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean hint(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingHints()) {
|
||||
if (!thePass && doingHints() && !suppressMsg(path, theMessage)) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.INFORMATION, null);
|
||||
}
|
||||
|
@ -464,7 +424,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean rule(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
if (!thePass && doingErrors() && !suppressMsg(path, theMessage)) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.ERROR, theMessage);
|
||||
}
|
||||
|
@ -472,7 +432,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean ruleInv(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String theMessage, String invId, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
if (!thePass && doingErrors() && !suppressMsg(path, theMessage)) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.ERROR, invId).setInvId(invId);
|
||||
}
|
||||
|
@ -480,7 +440,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean rule(List<ValidationMessage> errors, String ruleDate, IssueType type, NodeStack stack, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
if (!thePass && doingErrors() && !suppressMsg(stack.getLiteralPath(), theMessage)) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, stack.line(), stack.col(), stack.getLiteralPath(), message, IssueSeverity.ERROR, theMessage);
|
||||
}
|
||||
|
@ -492,7 +452,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean rulePlural(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, int num, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
if (!thePass && doingErrors() && !suppressMsg(path, theMessage)) {
|
||||
String message = context.formatMessagePlural(num, theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, message, IssueSeverity.ERROR, theMessage);
|
||||
}
|
||||
|
@ -500,7 +460,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean txRule(List<ValidationMessage> errors, String ruleDate, String txLink, IssueType type, int line, int col, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
if (!thePass && doingErrors() && !suppressMsg(path, theMessage)) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
ValidationMessage vm = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, message, IssueSeverity.ERROR).setMessageId(idForMessage(theMessage, message));
|
||||
vm.setRuleDate(ruleDate);
|
||||
|
@ -538,7 +498,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean rule(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
if (!thePass && doingErrors() && !suppressMsg(CommaSeparatedStringBuilder.join(".", pathParts), theMessage)) {
|
||||
String path = toPath(pathParts);
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage);
|
||||
|
@ -556,7 +516,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
|
||||
|
||||
protected boolean rule(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
if (!thePass && doingErrors() && !suppressMsg(path, theMessage)) {
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage);
|
||||
}
|
||||
|
@ -564,7 +524,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean rulePlural(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, int num, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingErrors()) {
|
||||
if (!thePass && doingErrors() && !suppressMsg(path, theMessage)) {
|
||||
String message = context.formatMessagePlural(num, theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.ERROR, theMessage);
|
||||
}
|
||||
|
@ -630,7 +590,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, msg)) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
IssueSeverity severity = IssueSeverity.WARNING;
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, severity, msg);
|
||||
|
@ -640,7 +600,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, String id, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, msg)) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
IssueSeverity severity = IssueSeverity.WARNING;
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, severity, id);
|
||||
|
@ -650,7 +610,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean warningInv(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, String invId, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, invId)) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
IssueSeverity severity = IssueSeverity.WARNING;
|
||||
String id = idForMessage(msg, nmsg);
|
||||
|
@ -669,7 +629,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean warningPlural(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, int num, String msg, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, msg)) {
|
||||
String nmsg = context.formatMessagePlural(num, msg, theMessageArguments);
|
||||
IssueSeverity severity = IssueSeverity.WARNING;
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, severity, msg);
|
||||
|
@ -711,7 +671,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean txWarning(List<ValidationMessage> errors, String ruleDate, String txLink, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, msg)) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
ValidationMessage vmsg = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(idForMessage(msg, nmsg));
|
||||
vmsg.setRuleDate(ruleDate);
|
||||
|
@ -744,7 +704,9 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
vmsg.setMessageId(issue.getExtensionString(ToolingExtensions.EXT_ISSUE_MSG_ID));
|
||||
}
|
||||
|
||||
errors.add(vmsg);
|
||||
if (!suppressMsg(path, vmsg.getMessageId())) {
|
||||
errors.add(vmsg);
|
||||
}
|
||||
return vmsg;
|
||||
}
|
||||
|
||||
|
@ -760,7 +722,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean txWarningForLaterRemoval(Object location, List<ValidationMessage> errors, String ruleDate, String txLink, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, msg)) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
ValidationMessage vmsg = new ValidationMessage(Source.TerminologyEngine, type, line, col, path, nmsg, IssueSeverity.WARNING).setTxLink(txLink).setMessageId(msg);
|
||||
vmsg.setRuleDate(ruleDate);
|
||||
|
@ -789,7 +751,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean warningOrError(boolean isError, List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass) {
|
||||
if (!thePass && !suppressMsg(path, msg)) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
IssueSeverity lvl = isError ? IssueSeverity.ERROR : IssueSeverity.WARNING;
|
||||
if (doingLevel(lvl)) {
|
||||
|
@ -805,7 +767,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
protected boolean hintOrError(boolean isError, List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass) {
|
||||
if (!thePass && !suppressMsg(path, msg)) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
IssueSeverity lvl = isError ? IssueSeverity.ERROR : IssueSeverity.INFORMATION;
|
||||
if (doingLevel(lvl)) {
|
||||
|
@ -824,7 +786,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(CommaSeparatedStringBuilder.join(".", pathParts), theMessage)) {
|
||||
String path = toPath(pathParts);
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.WARNING, theMessage);
|
||||
|
@ -840,7 +802,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean warning(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, msg)) {
|
||||
String message = context.formatMessage(msg, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.WARNING, null);
|
||||
}
|
||||
|
@ -855,7 +817,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean warningOrHint(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, boolean warning, String msg, Object... theMessageArguments) {
|
||||
if (!thePass) {
|
||||
if (!thePass && !suppressMsg(path, msg)) {
|
||||
String message = context.formatMessage(msg, theMessageArguments);
|
||||
IssueSeverity lvl = warning ? IssueSeverity.WARNING : IssueSeverity.INFORMATION;
|
||||
if (doingLevel(lvl)) {
|
||||
|
@ -873,7 +835,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean warningHtml(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg, String html) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, msg)) {
|
||||
addValidationMessage(errors, ruleDate, type, path, msg, html, IssueSeverity.WARNING, null);
|
||||
}
|
||||
return thePass;
|
||||
|
@ -887,7 +849,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean warningHtml(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, msg)) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, path, nmsg, html, IssueSeverity.WARNING, msg);
|
||||
}
|
||||
|
@ -903,7 +865,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean suppressedwarning(List<ValidationMessage> errors, String ruleDate, IssueType type, int line, int col, String path, boolean thePass, String msg, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, msg)) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, line, col, path, nmsg, IssueSeverity.INFORMATION, msg);
|
||||
}
|
||||
|
@ -919,7 +881,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean suppressedwarning(List<ValidationMessage> errors, String ruleDate, IssueType type, List<String> pathParts, boolean thePass, String theMessage, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(CommaSeparatedStringBuilder.join(".", pathParts), theMessage)) {
|
||||
String path = toPath(pathParts);
|
||||
String message = context.formatMessage(theMessage, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, -1, -1, path, message, IssueSeverity.INFORMATION, theMessage);
|
||||
|
@ -974,7 +936,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
* @return Returns <code>thePass</code> (in other words, returns <code>true</code> if the rule did not fail validation)
|
||||
*/
|
||||
protected boolean suppressedwarning(List<ValidationMessage> errors, String ruleDate, IssueType type, String path, boolean thePass, String msg, String html, Object... theMessageArguments) {
|
||||
if (!thePass && doingWarnings()) {
|
||||
if (!thePass && doingWarnings() && !suppressMsg(path, msg)) {
|
||||
String nmsg = context.formatMessage(msg, theMessageArguments);
|
||||
addValidationMessage(errors, ruleDate, type, path, nmsg, html, IssueSeverity.INFORMATION, msg);
|
||||
}
|
||||
|
@ -1681,4 +1643,17 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
return false;
|
||||
}
|
||||
|
||||
public IValidationPolicyAdvisor getPolicyAdvisor() {
|
||||
return policyAdvisor;
|
||||
}
|
||||
|
||||
public void setPolicyAdvisor(IValidationPolicyAdvisor advisor) {
|
||||
if (advisor == null) {
|
||||
throw new Error("Cannot set advisor to null");
|
||||
}
|
||||
this.policyAdvisor = advisor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1288,4 +1288,14 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
|
|||
definition, structure, resource, valid, msgServices, messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean suppressMessageId(String path, String messageId) {
|
||||
return policyAdvisor.suppressMessageId(path, messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReferenceValidationPolicy getReferencePolicy() {
|
||||
return ReferenceValidationPolicy.IGNORE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -376,6 +376,9 @@ public class ValidatorCli {
|
|||
((StandaloneTask) cliTask).executeTask(cliContext,params,tt,tts);
|
||||
}
|
||||
|
||||
if (cliContext.getAdvisorFile() != null) {
|
||||
System.out.println("Note: Some validation issues might be hidden by the advisor settings in the file "+cliContext.getAdvisorFile());
|
||||
}
|
||||
System.out.println("Done. " + tt.report()+". Max Memory = "+Utilities.describeSize(Runtime.getRuntime().maxMemory()));
|
||||
SystemExitManager.finish();
|
||||
}
|
||||
|
|
|
@ -132,6 +132,12 @@ public class CliContext {
|
|||
@JsonProperty("showTimes")
|
||||
private boolean showTimes = false;
|
||||
|
||||
@JsonProperty("showTerminologyRouting")
|
||||
private boolean showTerminologyRouting = false;
|
||||
|
||||
@JsonProperty("clearTxCache")
|
||||
private boolean clearTxCache = false;
|
||||
|
||||
@JsonProperty("locale")
|
||||
private String locale = Locale.ENGLISH.toLanguageTag();
|
||||
|
||||
|
@ -172,6 +178,9 @@ public class CliContext {
|
|||
@JsonProperty("noExperimentalContent")
|
||||
private boolean noExperimentalContent;
|
||||
|
||||
@JsonProperty("advisorFile")
|
||||
private String advisorFile;
|
||||
|
||||
@JsonProperty("baseEngine")
|
||||
public String getBaseEngine() {
|
||||
return baseEngine;
|
||||
|
@ -754,6 +763,22 @@ public class CliContext {
|
|||
this.showTimes = showTimes;
|
||||
}
|
||||
|
||||
public boolean isShowTerminologyRouting() {
|
||||
return showTerminologyRouting;
|
||||
}
|
||||
|
||||
public void setShowTerminologyRouting(boolean showTerminologyRouting) {
|
||||
this.showTerminologyRouting = showTerminologyRouting;
|
||||
}
|
||||
|
||||
public boolean isClearTxCache() {
|
||||
return clearTxCache;
|
||||
}
|
||||
|
||||
public void setClearTxCache(boolean clearTxCache) {
|
||||
this.clearTxCache = clearTxCache;
|
||||
}
|
||||
|
||||
public String getOutputStyle() {
|
||||
return outputStyle;
|
||||
}
|
||||
|
@ -852,6 +877,7 @@ public class CliContext {
|
|||
Objects.equals(watchScanDelay, that.watchScanDelay) &&
|
||||
Objects.equals(unknownCodeSystemsCauseErrors, that.unknownCodeSystemsCauseErrors) &&
|
||||
Objects.equals(noExperimentalContent, that.noExperimentalContent) &&
|
||||
Objects.equals(advisorFile, that.advisorFile) &&
|
||||
Objects.equals(watchSettleTime, that.watchSettleTime) ;
|
||||
}
|
||||
|
||||
|
@ -860,7 +886,7 @@ public class CliContext {
|
|||
return Objects.hash(baseEngine, doNative, extensions, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching,
|
||||
noExtensibleBindingMessages, noInvariants, displayWarnings, wantInvariantsInMessages, map, output, outputSuffix, htmlOutput, txServer, sv, txLog, txCache, mapLog, lang, srcLang, tgtLang, fhirpath, snomedCT,
|
||||
targetVer, igs, questionnaireMode, level, profiles, sources, inputs, mode, locale, locations, crumbTrails, showMessageIds, forPublication, showTimes, allowExampleUrls, outputStyle, jurisdiction, noUnicodeBiDiControlChars,
|
||||
watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, noExperimentalContent, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
|
||||
watchMode, watchScanDelay, watchSettleTime, bestPracticeLevel, unknownCodeSystemsCauseErrors, noExperimentalContent, advisorFile, htmlInMarkdownCheck, allowDoubleQuotesInFHIRPath, checkIPSCodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -922,6 +948,7 @@ public class CliContext {
|
|||
", watchScanDelay=" + watchScanDelay +
|
||||
", unknownCodeSystemsCauseErrors=" + unknownCodeSystemsCauseErrors +
|
||||
", noExperimentalContent=" + noExperimentalContent +
|
||||
", advisorFile=" + advisorFile +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
@ -1002,5 +1029,15 @@ public class CliContext {
|
|||
this.noExperimentalContent = noExperimentalContent;
|
||||
}
|
||||
|
||||
@JsonProperty("advisorFile")
|
||||
public String getAdvisorFile() {
|
||||
return advisorFile;
|
||||
}
|
||||
|
||||
@JsonProperty("advisorFile")
|
||||
public void setAdvisorFile(String advisorFile) {
|
||||
this.advisorFile = advisorFile;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -17,12 +17,14 @@ import org.hl7.fhir.exceptions.FHIRException;
|
|||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.context.IWorkerContextManager;
|
||||
import org.hl7.fhir.r5.elementmodel.Element;
|
||||
import org.hl7.fhir.r5.elementmodel.Element.SpecialElement;
|
||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
|
||||
import org.hl7.fhir.r5.utils.validation.IMessagingServices;
|
||||
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidatorResourceFetcher;
|
||||
|
@ -41,13 +43,14 @@ import org.hl7.fhir.utilities.json.model.JsonObject;
|
|||
import org.hl7.fhir.utilities.json.parser.JsonParser;
|
||||
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.validation.cli.utils.Common;
|
||||
import org.hl7.fhir.validation.instance.advisor.BasePolicyAdvisorForFullValidation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
||||
public class StandAloneValidatorFetcher extends BasePolicyAdvisorForFullValidation implements IValidatorResourceFetcher, IValidationPolicyAdvisor, IWorkerContextManager.ICanonicalResourceLocator {
|
||||
public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IValidationPolicyAdvisor, IWorkerContextManager.ICanonicalResourceLocator {
|
||||
|
||||
List<String> mappingsUris = new ArrayList<>();
|
||||
private FilesystemPackageCacheManager pcm;
|
||||
|
@ -56,12 +59,13 @@ public class StandAloneValidatorFetcher extends BasePolicyAdvisorForFullValidati
|
|||
private Map<String, Boolean> urlList = new HashMap<>();
|
||||
private Map<String, String> pidList = new HashMap<>();
|
||||
private Map<String, NpmPackage> pidMap = new HashMap<>();
|
||||
|
||||
private IValidationPolicyAdvisor policyAdvisor;
|
||||
|
||||
public StandAloneValidatorFetcher(FilesystemPackageCacheManager pcm, IWorkerContext context, IPackageInstaller installer) {
|
||||
super(ReferenceValidationPolicy.IGNORE);
|
||||
this.pcm = pcm;
|
||||
this.context = context;
|
||||
this.installer = installer;
|
||||
this.policyAdvisor = new BasePolicyAdvisorForFullValidation(ReferenceValidationPolicy.IGNORE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -297,4 +301,55 @@ public class StandAloneValidatorFetcher extends BasePolicyAdvisorForFullValidati
|
|||
return new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean suppressMessageId(String path, String messageId) {
|
||||
return policyAdvisor.suppressMessageId(path, messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, Object appContext,
|
||||
StructureDefinition structure, ElementDefinition element, String containerType, String containerId,
|
||||
SpecialElement containingResourceType, String path, String url) {
|
||||
return policyAdvisor.policyForContained(validator, appContext, structure, element, containerType, containerId, containingResourceType, path, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<ResourceValidationAction> policyForResource(IResourceValidator validator, Object appContext,
|
||||
StructureDefinition type, String path) {
|
||||
return policyAdvisor.policyForResource(validator, appContext, type, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<ElementValidationAction> policyForElement(IResourceValidator validator, Object appContext,
|
||||
StructureDefinition structure, ElementDefinition element, String path) {
|
||||
return policyAdvisor.policyForElement(validator, appContext, structure, element, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<CodedContentValidationAction> policyForCodedContent(IResourceValidator validator, Object appContext,
|
||||
String stackPath, ElementDefinition definition, StructureDefinition structure, BindingKind kind,
|
||||
AdditionalBindingPurpose purpose, ValueSet valueSet, List<String> systems) {
|
||||
return policyAdvisor.policyForCodedContent(validator, appContext, stackPath, definition, structure, kind, purpose, valueSet, systems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StructureDefinition> getImpliedProfilesForResource(IResourceValidator validator, Object appContext,
|
||||
String stackPath, ElementDefinition definition, StructureDefinition structure, Element resource, boolean valid,
|
||||
IMessagingServices msgServices, List<ValidationMessage> messages) {
|
||||
return policyAdvisor.getImpliedProfilesForResource(validator, appContext, stackPath, definition, structure, resource, valid, msgServices, messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReferenceValidationPolicy getReferencePolicy() {
|
||||
return policyAdvisor.getReferencePolicy();
|
||||
}
|
||||
|
||||
public IValidationPolicyAdvisor getPolicyAdvisor() {
|
||||
return policyAdvisor;
|
||||
}
|
||||
|
||||
public void setPolicyAdvisor(IValidationPolicyAdvisor policyAdvisor) {
|
||||
this.policyAdvisor = policyAdvisor;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.hl7.fhir.r5.renderers.spreadsheets.ConceptMapSpreadsheetGenerator;
|
|||
import org.hl7.fhir.r5.renderers.spreadsheets.StructureDefinitionSpreadsheetGenerator;
|
||||
import org.hl7.fhir.r5.renderers.spreadsheets.ValueSetSpreadsheetGenerator;
|
||||
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
|
||||
import org.hl7.fhir.r5.terminologies.client.TerminologyClientManager.InternalLogEvent;
|
||||
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache;
|
||||
import org.hl7.fhir.utilities.FhirPublication;
|
||||
import org.hl7.fhir.utilities.SystemExitManager;
|
||||
|
@ -69,6 +70,8 @@ import org.hl7.fhir.validation.cli.renderers.ValidationOutputRenderer;
|
|||
import org.hl7.fhir.validation.cli.utils.Common;
|
||||
import org.hl7.fhir.validation.cli.utils.EngineMode;
|
||||
import org.hl7.fhir.validation.cli.utils.VersionSourceInformation;
|
||||
import org.hl7.fhir.validation.instance.advisor.JsonDrivenPolicyAdvisor;
|
||||
import org.hl7.fhir.validation.instance.advisor.TextDrivenPolicyAdvisor;
|
||||
|
||||
public class ValidationService {
|
||||
|
||||
|
@ -155,6 +158,7 @@ public class ValidationService {
|
|||
if (request.getCliContext().isShowTimes()) {
|
||||
response.getValidationTimes().put(fileToValidate.getFileName(), validatedFragments.getValidationTime());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,6 +293,19 @@ public class ValidationService {
|
|||
TextFile.stringToFile(html, cliContext.getHtmlOutput());
|
||||
System.out.println("HTML Summary in " + cliContext.getHtmlOutput());
|
||||
}
|
||||
|
||||
if (cliContext.isShowTerminologyRouting()) {
|
||||
System.out.println("");
|
||||
System.out.println("Terminology Routing Dump ---------------------------------------");
|
||||
if (validator.getContext().getTxClientManager().getInternalLog().isEmpty()) {
|
||||
System.out.println("(nothing happened)");
|
||||
} else {
|
||||
for (InternalLogEvent log : validator.getContext().getTxClientManager().getInternalLog()) {
|
||||
System.out.println(log.getMessage()+" -> "+log.getServer()+" (for VS "+log.getVs()+" with systems '"+log.getSystems()+"', choices = '"+log.getChoices()+"')");
|
||||
}
|
||||
}
|
||||
validator.getContext().getTxClientManager().getInternalLog().clear();
|
||||
}
|
||||
}
|
||||
if (watch != ValidatorWatchMode.NONE) {
|
||||
if (statusNeeded) {
|
||||
|
@ -545,6 +562,10 @@ public class ValidationService {
|
|||
System.out.println(" No Terminology Cache");
|
||||
} else {
|
||||
System.out.println(" Terminology Cache at "+validationEngine.getContext().getTxCache().getFolder());
|
||||
if (cliContext.isClearTxCache()) {
|
||||
System.out.println(" Terminology Cache Entries Cleaned out");
|
||||
validationEngine.getContext().getTxCache().clear();
|
||||
}
|
||||
}
|
||||
System.out.print(" Get set... ");
|
||||
validationEngine.setQuestionnaireMode(cliContext.getQuestionnaireMode());
|
||||
|
@ -584,6 +605,13 @@ public class ValidationService {
|
|||
validationEngine.setFetcher(fetcher);
|
||||
validationEngine.getContext().setLocator(fetcher);
|
||||
validationEngine.setPolicyAdvisor(fetcher);
|
||||
if (cliContext.getAdvisorFile() != null) {
|
||||
if (cliContext.getAdvisorFile().endsWith(".json")) {
|
||||
fetcher.setPolicyAdvisor(new JsonDrivenPolicyAdvisor(fetcher.getPolicyAdvisor(), new File(cliContext.getAdvisorFile())));
|
||||
} else {
|
||||
fetcher.setPolicyAdvisor(new TextDrivenPolicyAdvisor(fetcher.getPolicyAdvisor(), new File(cliContext.getAdvisorFile())));
|
||||
}
|
||||
}
|
||||
}
|
||||
validationEngine.getBundleValidationRules().addAll(cliContext.getBundleValidationRules());
|
||||
validationEngine.setJurisdiction(CodeSystemUtilities.readCoding(cliContext.getJurisdiction()));
|
||||
|
|
|
@ -54,6 +54,8 @@ public class Params {
|
|||
public static final String TERMINOLOGY = "-tx";
|
||||
public static final String TERMINOLOGY_LOG = "-txLog";
|
||||
public static final String TERMINOLOGY_CACHE = "-txCache";
|
||||
public static final String TERMINOLOGY_ROUTING = "-tx-routing";
|
||||
public static final String TERMINOLOGY_CACHE_CLEAR = "-clear-tx-cache";
|
||||
public static final String LOG = "-log";
|
||||
public static final String LANGUAGE = "-language";
|
||||
public static final String IMPLEMENTATION_GUIDE = "-ig";
|
||||
|
@ -86,6 +88,7 @@ public class Params {
|
|||
public static final String SHOW_TIMES = "-show-times";
|
||||
public static final String ALLOW_EXAMPLE_URLS = "-allow-example-urls";
|
||||
public static final String OUTPUT_STYLE = "-output-style";
|
||||
public static final String ADVSIOR_FILE = "-advisor-file";
|
||||
public static final String DO_IMPLICIT_FHIRPATH_STRING_CONVERSION = "-implicit-fhirpath-string-conversions";
|
||||
public static final String JURISDICTION = "-jurisdiction";
|
||||
public static final String HTML_IN_MARKDOWN = "-html-in-markdown";
|
||||
|
@ -339,10 +342,22 @@ public class Params {
|
|||
} else {
|
||||
throw new Error("Value for "+ALLOW_EXAMPLE_URLS+" not understood: "+bl);
|
||||
}
|
||||
} else if (args[i].equals(TERMINOLOGY_ROUTING)) {
|
||||
cliContext.setShowTerminologyRouting(true);
|
||||
} else if (args[i].equals(TERMINOLOGY_CACHE_CLEAR)) {
|
||||
cliContext.setClearTxCache(true);
|
||||
} else if (args[i].equals(SHOW_TIMES)) {
|
||||
cliContext.setShowTimes(true);
|
||||
} else if (args[i].equals(OUTPUT_STYLE)) {
|
||||
cliContext.setOutputStyle(args[++i]);
|
||||
} else if (args[i].equals(ADVSIOR_FILE)) {
|
||||
cliContext.setAdvisorFile(args[++i]);
|
||||
File f = new File(cliContext.getAdvisorFile());
|
||||
if (!f.exists()) {
|
||||
throw new Error("Cannot find advisor file "+cliContext.getAdvisorFile());
|
||||
} else if (!Utilities.existsInList(Utilities.getFileExtension(f.getName()), "json", "txt")) {
|
||||
throw new Error("Advisor file "+cliContext.getAdvisorFile()+" must be a .json or a .txt file");
|
||||
}
|
||||
} else if (args[i].equals(SCAN)) {
|
||||
cliContext.setMode(EngineMode.SCAN);
|
||||
} else if (args[i].equals(TERMINOLOGY)) {
|
||||
|
|
|
@ -574,7 +574,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
private boolean noBindingMsgSuppressed;
|
||||
private Map<String, Element> fetchCache = new HashMap<>();
|
||||
private HashMap<Element, ResourceValidationTracker> resourceTracker = new HashMap<>();
|
||||
private IValidationPolicyAdvisor policyAdvisor = new BasePolicyAdvisorForFullValidation(ReferenceValidationPolicy.CHECK_VALID);
|
||||
long time = 0;
|
||||
long start = 0;
|
||||
long lastlog = 0;
|
||||
|
@ -664,21 +663,6 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IValidationPolicyAdvisor getPolicyAdvisor() {
|
||||
return policyAdvisor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IResourceValidator setPolicyAdvisor(IValidationPolicyAdvisor advisor) {
|
||||
if (advisor == null) {
|
||||
throw new Error("Cannot set advisor to null");
|
||||
}
|
||||
this.policyAdvisor = advisor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IValidationProfileUsageTracker getTracker() {
|
||||
return this.tracker;
|
||||
}
|
||||
|
|
|
@ -169,5 +169,15 @@ public class BasePolicyAdvisorForFullValidation implements IValidationPolicyAdvi
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean suppressMessageId(String path, String messageId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReferenceValidationPolicy getReferencePolicy() {
|
||||
return refpol;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -18,60 +18,35 @@ import org.hl7.fhir.r5.utils.validation.constants.BindingKind;
|
|||
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
|
||||
import org.hl7.fhir.utilities.json.JsonException;
|
||||
import org.hl7.fhir.utilities.json.model.JsonElement;
|
||||
import org.hl7.fhir.utilities.json.model.JsonObject;
|
||||
import org.hl7.fhir.utilities.json.parser.JsonParser;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
|
||||
public class JsonDrivenPolicyAdvisor implements IValidationPolicyAdvisor {
|
||||
public class JsonDrivenPolicyAdvisor extends RulesDrivenPolicyAdvisor {
|
||||
|
||||
private JsonObject config;
|
||||
private IValidationPolicyAdvisor base;
|
||||
|
||||
public JsonDrivenPolicyAdvisor(IValidationPolicyAdvisor base, JsonObject config) {
|
||||
this.base = base;
|
||||
this.config = config;
|
||||
public JsonDrivenPolicyAdvisor(IValidationPolicyAdvisor base, File source) throws JsonException, IOException {
|
||||
super(base);
|
||||
load(source);
|
||||
}
|
||||
|
||||
public JsonDrivenPolicyAdvisor(String config) throws JsonException, IOException {
|
||||
this.config = JsonParser.parseObject(config, true);
|
||||
public JsonDrivenPolicyAdvisor(ReferenceValidationPolicy refpol, File source) throws JsonException, IOException {
|
||||
super(refpol);
|
||||
load(source);
|
||||
}
|
||||
|
||||
public JsonDrivenPolicyAdvisor(File config) throws JsonException, IOException {
|
||||
this.config = JsonParser.parseObject(new FileInputStream(config), true);
|
||||
}
|
||||
|
||||
public JsonDrivenPolicyAdvisor(FileInputStream config) throws JsonException, IOException {
|
||||
this.config = JsonParser.parseObject(config, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReferenceValidationPolicy policyForReference(IResourceValidator validator, Object appContext, String path, String url) {
|
||||
return base.policyForReference(validator, appContext, path, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, Object appContext, StructureDefinition structure, ElementDefinition element, String containerType, String containerId, SpecialElement containingResourceType, String path, String url) {
|
||||
return base.policyForContained(validator, appContext, structure, element, containerType, containerId, containingResourceType, path, url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<ResourceValidationAction> policyForResource(IResourceValidator validator, Object appContext, StructureDefinition type, String path) {
|
||||
return base.policyForResource(validator, appContext, type, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<ElementValidationAction> policyForElement(IResourceValidator validator, Object appContext, StructureDefinition structure, ElementDefinition element, String path) {
|
||||
return base.policyForElement(validator, appContext, structure, element, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<CodedContentValidationAction> policyForCodedContent(IResourceValidator validator, Object appContext, String stackPath, ElementDefinition definition, StructureDefinition structure, BindingKind kind, AdditionalBindingPurpose purpose, ValueSet valueSet, List<String> systems) {
|
||||
return base.policyForCodedContent(validator, appContext, stackPath, definition, structure, kind, purpose, valueSet, systems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StructureDefinition> getImpliedProfilesForResource(IResourceValidator validator, Object appContext, String stackPath, ElementDefinition definition, StructureDefinition structure, Element resource, boolean valid, IMessagingServices msgServices, List<ValidationMessage> messages) {
|
||||
return base.getImpliedProfilesForResource(validator, appContext, stackPath, definition, structure, resource, valid, msgServices, messages);
|
||||
private void load(File source) throws JsonException, IOException {
|
||||
JsonObject json = JsonParser.parseObject(source);
|
||||
for (JsonElement e : json.forceArray("suppress").getItems()) {
|
||||
String s = e.asString();
|
||||
String id = s;
|
||||
String path = null;
|
||||
if (s.contains("@")) {
|
||||
id = s.substring(0, s.indexOf("@"));
|
||||
path = s.substring(s.indexOf("@")+1);
|
||||
}
|
||||
addSuppressMessageRule(id, path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
package org.hl7.fhir.validation.instance.advisor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.hl7.fhir.r5.elementmodel.Element;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.utils.validation.IMessagingServices;
|
||||
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.AdditionalBindingPurpose;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.CodedContentValidationAction;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.ElementValidationAction;
|
||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor.ResourceValidationAction;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.BindingKind;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.CodedContentValidationPolicy;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
|
||||
import org.hl7.fhir.utilities.validation.ValidationMessage;
|
||||
|
||||
public class RulesDrivenPolicyAdvisor extends BasePolicyAdvisorForFullValidation {
|
||||
|
||||
private IValidationPolicyAdvisor base;
|
||||
|
||||
public RulesDrivenPolicyAdvisor(ReferenceValidationPolicy refpol) {
|
||||
super(refpol);
|
||||
base = null;
|
||||
}
|
||||
|
||||
public RulesDrivenPolicyAdvisor(IValidationPolicyAdvisor base) {
|
||||
super(base.getReferencePolicy());
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
private class SuppressMessageRule {
|
||||
private String id;
|
||||
private String path;
|
||||
protected SuppressMessageRule(String id, String path) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.path = path;
|
||||
}
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
public boolean matches(String mid, String p) {
|
||||
if (((id == null) || id.equals(mid)) && ((path == null) || path.equals(p))) {
|
||||
suppressed++;
|
||||
return true;
|
||||
} else if (((id == null) || mid.matches(id)) && ((path == null) || p.matches(path))) {
|
||||
suppressed++;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<SuppressMessageRule> suppressMessageRules = new ArrayList<>();
|
||||
private int suppressed = 0;
|
||||
|
||||
protected void addSuppressMessageRule(String id, String path) {
|
||||
suppressMessageRules.add(new SuppressMessageRule(id, path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean suppressMessageId(String path, String messageId) {
|
||||
for (SuppressMessageRule rule : suppressMessageRules) {
|
||||
if (rule.matches(messageId, path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (base != null) {
|
||||
return base.suppressMessageId(path, messageId);
|
||||
} else {
|
||||
return super.suppressMessageId(path, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReferenceValidationPolicy policyForReference(IResourceValidator validator,
|
||||
Object appContext,
|
||||
String path,
|
||||
String url) {
|
||||
if (base != null) {
|
||||
return base.policyForReference(validator, appContext, path, url);
|
||||
} else {
|
||||
return super.policyForReference(validator, appContext, path, url);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator,
|
||||
Object appContext,
|
||||
StructureDefinition structure,
|
||||
ElementDefinition element,
|
||||
String containerType,
|
||||
String containerId,
|
||||
Element.SpecialElement containingResourceType,
|
||||
String path,
|
||||
String url) {
|
||||
if (base != null) {
|
||||
return base.policyForContained(validator, appContext, structure, element, containerType, containerId, containingResourceType, path, url);
|
||||
} else {
|
||||
return super.policyForContained(validator, appContext, structure, element, containerType, containerId, containingResourceType, path, url);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<ResourceValidationAction> policyForResource(IResourceValidator validator,
|
||||
Object appContext,
|
||||
StructureDefinition type,
|
||||
String path) {
|
||||
if (base != null) {
|
||||
return base.policyForResource(validator, appContext, type, path);
|
||||
} else {
|
||||
return super.policyForResource(validator, appContext, type, path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<ElementValidationAction> policyForElement(IResourceValidator validator,
|
||||
Object appContext,
|
||||
StructureDefinition structure,
|
||||
ElementDefinition element,
|
||||
String path) {
|
||||
if (base != null) {
|
||||
return base.policyForElement(validator, appContext, structure, element, path);
|
||||
} else {
|
||||
return super.policyForElement(validator, appContext, structure, element, path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<CodedContentValidationAction> policyForCodedContent(IResourceValidator validator,
|
||||
Object appContext,
|
||||
String stackPath,
|
||||
ElementDefinition definition,
|
||||
StructureDefinition structure,
|
||||
BindingKind kind,
|
||||
AdditionalBindingPurpose purpose,
|
||||
ValueSet valueSet,
|
||||
List<String> systems) {
|
||||
if (base != null) {
|
||||
return base.policyForCodedContent(validator, appContext, stackPath, definition, structure, kind, purpose, valueSet, systems);
|
||||
} else {
|
||||
return super.policyForCodedContent(validator, appContext, stackPath, definition, structure, kind, purpose, valueSet, systems);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StructureDefinition> getImpliedProfilesForResource(IResourceValidator validator,
|
||||
Object appContext,
|
||||
String stackPath,
|
||||
ElementDefinition definition,
|
||||
StructureDefinition structure,
|
||||
Element resource,
|
||||
boolean valid,
|
||||
IMessagingServices msgServices,
|
||||
List<ValidationMessage> messages) {
|
||||
if (base != null) {
|
||||
return base.getImpliedProfilesForResource(validator, appContext, stackPath, definition, structure, resource, valid, msgServices, messages);
|
||||
} else {
|
||||
return super.getImpliedProfilesForResource(validator, appContext, stackPath, definition, structure, resource, valid, msgServices, messages);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package org.hl7.fhir.validation.instance.advisor;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
|
||||
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.json.JsonException;
|
||||
|
||||
public class TextDrivenPolicyAdvisor extends RulesDrivenPolicyAdvisor {
|
||||
|
||||
public TextDrivenPolicyAdvisor(IValidationPolicyAdvisor base, File source) throws JsonException, IOException {
|
||||
super(base);
|
||||
load(source);
|
||||
}
|
||||
|
||||
public TextDrivenPolicyAdvisor(ReferenceValidationPolicy refpol, File source) throws JsonException, IOException {
|
||||
super(refpol);
|
||||
load(source);
|
||||
}
|
||||
|
||||
private void load(File source) throws JsonException, IOException {
|
||||
BufferedReader reader = new BufferedReader(new FileReader(source));
|
||||
String line = reader.readLine();
|
||||
while (line != null) {
|
||||
processLine(line);
|
||||
line = reader.readLine();
|
||||
}
|
||||
reader.close();
|
||||
}
|
||||
|
||||
private void processLine(String line) {
|
||||
line = line.trim();
|
||||
if (Utilities.noString(line) || line.startsWith("#")) {
|
||||
return;
|
||||
}
|
||||
if (line.startsWith("-")) {
|
||||
String s = line.substring(1).trim();
|
||||
String id = s;
|
||||
String path = null;
|
||||
if (s.contains("@")) {
|
||||
id = s.substring(0, s.indexOf("@"));
|
||||
path = s.substring(s.indexOf("@")+1);
|
||||
}
|
||||
addSuppressMessageRule(id, path);
|
||||
} else {
|
||||
// ignore it for now
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ Some notes on this approach:
|
|||
* the messageId is directly tied to the format of the message. For some messages, there are multiple variants of the message, each with their own id, and these all need to be suppressed
|
||||
* message ids are stable (including across languages), but sometimes an existing message is improved in some contexts, and new message ids are introduced in later versions
|
||||
* the underlying validation still happens, even when the messages are suppressed
|
||||
|
||||
* for invariants in profiles, the message id is the profile URL and the invariant id e.g. http://hl7.org/fhir/StructureDefinition/DomainResource#dom-6
|
||||
|
||||
## Controlling what validation runs
|
||||
|
||||
|
|
|
@ -920,4 +920,14 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean suppressMessageId(String path, String messageId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReferenceValidationPolicy getReferencePolicy() {
|
||||
return ReferenceValidationPolicy.IGNORE;
|
||||
}
|
||||
}
|
2
pom.xml
2
pom.xml
|
@ -22,7 +22,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.5.26</validator_test_case_version>
|
||||
<validator_test_case_version>1.5.27-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>
|
||||
|
|
Loading…
Reference in New Issue