diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidationPolicyAdvisor.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidationPolicyAdvisor.java index c87508dcd..c55a533bd 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidationPolicyAdvisor.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/validation/IValidationPolicyAdvisor.java @@ -29,7 +29,7 @@ public interface IValidationPolicyAdvisor { * @param messageId - the message id (from messages.properties) * @return true if the validator should ignore the message */ - boolean suppressMessageId(String path, String messageId); + boolean isSuppressMessageId(String path, String messageId); /** * diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java index cb6f23fdd..d3cd56aab 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/BaseValidator.java @@ -278,7 +278,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi if (policyAdvisor == null) { return false; } else { - return policyAdvisor.suppressMessageId(path, theMessage); + return policyAdvisor.isSuppressMessageId(path, theMessage); } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java index 545670b98..863e02715 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/ValidationEngine.java @@ -1289,8 +1289,8 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP } @Override - public boolean suppressMessageId(String path, String messageId) { - return policyAdvisor.suppressMessageId(path, messageId); + public boolean isSuppressMessageId(String path, String messageId) { + return policyAdvisor.isSuppressMessageId(path, messageId); } @Override diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java index 20beab9a8..cdf7b1381 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/cli/services/StandAloneValidatorFetcher.java @@ -302,8 +302,8 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IV } @Override - public boolean suppressMessageId(String path, String messageId) { - return policyAdvisor.suppressMessageId(path, messageId); + public boolean isSuppressMessageId(String path, String messageId) { + return policyAdvisor.isSuppressMessageId(path, messageId); } @Override diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/BasePolicyAdvisorForFullValidation.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/BasePolicyAdvisorForFullValidation.java index 79b63eecb..434612dd7 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/BasePolicyAdvisorForFullValidation.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/BasePolicyAdvisorForFullValidation.java @@ -13,10 +13,6 @@ 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.ContainedReferenceValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; @@ -170,7 +166,7 @@ public class BasePolicyAdvisorForFullValidation implements IValidationPolicyAdvi } @Override - public boolean suppressMessageId(String path, String messageId) { + public boolean isSuppressMessageId(String path, String messageId) { return false; } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/JsonDrivenPolicyAdvisor.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/JsonDrivenPolicyAdvisor.java index 8121f9d62..0118d7674 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/JsonDrivenPolicyAdvisor.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/JsonDrivenPolicyAdvisor.java @@ -1,27 +1,16 @@ package org.hl7.fhir.validation.instance.advisor; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.util.EnumSet; -import java.util.List; -import org.hl7.fhir.r5.elementmodel.Element; -import org.hl7.fhir.r5.elementmodel.Element.SpecialElement; -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 javax.annotation.Nonnull; + import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; -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 extends RulesDrivenPolicyAdvisor { @@ -38,14 +27,19 @@ public class JsonDrivenPolicyAdvisor extends RulesDrivenPolicyAdvisor { 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; + @Nonnull String s = e.asString(); if (s.contains("@")) { - id = s.substring(0, s.indexOf("@")); - path = s.substring(s.indexOf("@")+1); + String id = s.substring(0, s.indexOf("@")); + String path = s.substring(s.indexOf("@")+1); + boolean regex = false; + if (path.startsWith("^")) { + regex = true; + path = path.substring(1); + } + addSuppressMessageRule(id, path, regex); + } else { + addSuppressMessageRule(s); } - addSuppressMessageRule(id, path); } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/RulesDrivenPolicyAdvisor.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/RulesDrivenPolicyAdvisor.java index fe5a9f4ad..942081e93 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/RulesDrivenPolicyAdvisor.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/RulesDrivenPolicyAdvisor.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.EnumSet; import java.util.List; +import javax.annotation.Nonnull; + import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.StructureDefinition; @@ -11,12 +13,7 @@ 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; @@ -38,48 +35,105 @@ public class RulesDrivenPolicyAdvisor extends BasePolicyAdvisorForFullValidation private class SuppressMessageRule { private String id; private String path; - protected SuppressMessageRule(String id, String path) { + private String[] pathSegments; + private boolean regex; + + protected SuppressMessageRule(@Nonnull String id, String path, boolean regex) { super(); this.id = id; this.path = path; + this.pathSegments = path.split("\\."); + this.regex = regex; } - public String getId() { - return id; + + protected SuppressMessageRule(@Nonnull String id) { + super(); + this.id = 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; + + public boolean matches(@Nonnull String mid, @Nonnull String path, String[] p) { + if (regex) { + return stringMatches(id, mid) && regexMatches(path, path); } else { + return stringMatches(id, mid) && pathMatches(pathSegments, p); + } + } + } + + // string matching + + boolean pathMatches(String[] specifier, String[] actual) { + if (specifier == null) { + return true; + } + for (int i = 0; i < specifier.length; i++) { + if (i == actual.length) { + return false; + } else if (!pathSegmentMatches(specifier[i], actual[i])) { return false; } } + if (actual.length > specifier.length) { + return specifier[specifier.length-1].equals("*"); + } else { + return true; + } + } + + boolean pathSegmentMatches(String specifier, String actual) { + if ("*".equals(specifier)) { + return true; + } else if (!specifier.contains("[")) { + if (actual.contains("[")) { + actual = actual.substring(0, actual.indexOf("[")); + } + return specifier.equals(actual); + } else { + return specifier.equals(actual); + } + } + + boolean stringMatches(String specifier, @Nonnull String actual) { + if (specifier == null) { + return true; + } else if (specifier.endsWith("*")) { + return specifier.substring(0, specifier.length()-1).equalsIgnoreCase(actual.substring(0, specifier.length()-1)); + } else { + return specifier.equalsIgnoreCase(actual); + } + } + + boolean regexMatches(String specifier, @Nonnull String actual) { + if (specifier == null) { + return true; + } else { + return actual.matches(specifier); + } } private List suppressMessageRules = new ArrayList<>(); private int suppressed = 0; - protected void addSuppressMessageRule(String id, String path) { - suppressMessageRules.add(new SuppressMessageRule(id, path)); + protected void addSuppressMessageRule(@Nonnull String id, String path, boolean regex) { + suppressMessageRules.add(new SuppressMessageRule(id, path, regex)); + } + + protected void addSuppressMessageRule(@Nonnull String id) { + suppressMessageRules.add(new SuppressMessageRule(id)); } @Override - public boolean suppressMessageId(String path, String messageId) { + public boolean isSuppressMessageId(String path, String messageId) { + String[] p = path.split("\\."); for (SuppressMessageRule rule : suppressMessageRules) { - if (rule.matches(messageId, path)) { + if (rule.matches(messageId, path, p)) { return true; } } if (base != null) { - return base.suppressMessageId(path, messageId); + return base.isSuppressMessageId(path, messageId); } else { - return super.suppressMessageId(path, messageId); + return super.isSuppressMessageId(path, messageId); } } diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/TextDrivenPolicyAdvisor.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/TextDrivenPolicyAdvisor.java index 2920d51ae..c078c2eb0 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/TextDrivenPolicyAdvisor.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/advisor/TextDrivenPolicyAdvisor.java @@ -5,6 +5,8 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; +import javax.annotation.Nonnull; + import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; import org.hl7.fhir.utilities.Utilities; @@ -38,14 +40,19 @@ public class TextDrivenPolicyAdvisor extends RulesDrivenPolicyAdvisor { return; } if (line.startsWith("-")) { - String s = line.substring(1).trim(); - String id = s; - String path = null; + @Nonnull String s = line.substring(1).trim(); if (s.contains("@")) { - id = s.substring(0, s.indexOf("@")); - path = s.substring(s.indexOf("@")+1); + String id = s.substring(0, s.indexOf("@")); + String path = s.substring(s.indexOf("@")+1); + boolean regex = false; + if (path.startsWith("^")) { + regex = true; + path = path.substring(1); + } + addSuppressMessageRule(id, path, regex); + } else { + addSuppressMessageRule(s); } - addSuppressMessageRule(id, path); } else { // ignore it for now } diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java index cb155d739..e4b712a70 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationTests.java @@ -922,7 +922,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe } @Override - public boolean suppressMessageId(String path, String messageId) { + public boolean isSuppressMessageId(String path, String messageId) { return false; }