rework rules based advisor

This commit is contained in:
Grahame Grieve 2024-10-14 12:31:51 +08:00
parent 3b8b2a94c3
commit f19f8f4ed2
9 changed files with 112 additions and 61 deletions

View File

@ -29,7 +29,7 @@ public interface IValidationPolicyAdvisor {
* @param messageId - the message id (from messages.properties) * @param messageId - the message id (from messages.properties)
* @return true if the validator should ignore the message * @return true if the validator should ignore the message
*/ */
boolean suppressMessageId(String path, String messageId); boolean isSuppressMessageId(String path, String messageId);
/** /**
* *

View File

@ -278,7 +278,7 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
if (policyAdvisor == null) { if (policyAdvisor == null) {
return false; return false;
} else { } else {
return policyAdvisor.suppressMessageId(path, theMessage); return policyAdvisor.isSuppressMessageId(path, theMessage);
} }
} }

View File

@ -1289,8 +1289,8 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
} }
@Override @Override
public boolean suppressMessageId(String path, String messageId) { public boolean isSuppressMessageId(String path, String messageId) {
return policyAdvisor.suppressMessageId(path, messageId); return policyAdvisor.isSuppressMessageId(path, messageId);
} }
@Override @Override

View File

@ -302,8 +302,8 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, IV
} }
@Override @Override
public boolean suppressMessageId(String path, String messageId) { public boolean isSuppressMessageId(String path, String messageId) {
return policyAdvisor.suppressMessageId(path, messageId); return policyAdvisor.isSuppressMessageId(path, messageId);
} }
@Override @Override

View File

@ -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.IMessagingServices;
import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; 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.BindingKind;
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
@ -170,7 +166,7 @@ public class BasePolicyAdvisorForFullValidation implements IValidationPolicyAdvi
} }
@Override @Override
public boolean suppressMessageId(String path, String messageId) { public boolean isSuppressMessageId(String path, String messageId) {
return false; return false;
} }

View File

@ -1,27 +1,16 @@
package org.hl7.fhir.validation.instance.advisor; package org.hl7.fhir.validation.instance.advisor;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.EnumSet;
import java.util.List;
import org.hl7.fhir.r5.elementmodel.Element; import javax.annotation.Nonnull;
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 org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; 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.r5.utils.validation.constants.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.json.JsonException; import org.hl7.fhir.utilities.json.JsonException;
import org.hl7.fhir.utilities.json.model.JsonElement; import org.hl7.fhir.utilities.json.model.JsonElement;
import org.hl7.fhir.utilities.json.model.JsonObject; import org.hl7.fhir.utilities.json.model.JsonObject;
import org.hl7.fhir.utilities.json.parser.JsonParser; import org.hl7.fhir.utilities.json.parser.JsonParser;
import org.hl7.fhir.utilities.validation.ValidationMessage;
public class JsonDrivenPolicyAdvisor extends RulesDrivenPolicyAdvisor { public class JsonDrivenPolicyAdvisor extends RulesDrivenPolicyAdvisor {
@ -38,14 +27,19 @@ public class JsonDrivenPolicyAdvisor extends RulesDrivenPolicyAdvisor {
private void load(File source) throws JsonException, IOException { private void load(File source) throws JsonException, IOException {
JsonObject json = JsonParser.parseObject(source); JsonObject json = JsonParser.parseObject(source);
for (JsonElement e : json.forceArray("suppress").getItems()) { for (JsonElement e : json.forceArray("suppress").getItems()) {
String s = e.asString(); @Nonnull String s = e.asString();
String id = s;
String path = null;
if (s.contains("@")) { if (s.contains("@")) {
id = s.substring(0, s.indexOf("@")); String id = s.substring(0, s.indexOf("@"));
path = s.substring(s.indexOf("@")+1); 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);
} }
} }

View File

@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import org.hl7.fhir.r5.elementmodel.Element; import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.StructureDefinition; 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.IMessagingServices;
import org.hl7.fhir.r5.utils.validation.IResourceValidator; import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; 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.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.ContainedReferenceValidationPolicy;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.validation.ValidationMessage; import org.hl7.fhir.utilities.validation.ValidationMessage;
@ -38,48 +35,105 @@ public class RulesDrivenPolicyAdvisor extends BasePolicyAdvisorForFullValidation
private class SuppressMessageRule { private class SuppressMessageRule {
private String id; private String id;
private String path; 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(); super();
this.id = id; this.id = id;
this.path = path; 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(@Nonnull String mid, @Nonnull String path, String[] p) {
} if (regex) {
public boolean matches(String mid, String p) { return stringMatches(id, mid) && regexMatches(path, path);
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 { } 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; 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<SuppressMessageRule> suppressMessageRules = new ArrayList<>(); private List<SuppressMessageRule> suppressMessageRules = new ArrayList<>();
private int suppressed = 0; private int suppressed = 0;
protected void addSuppressMessageRule(String id, String path) { protected void addSuppressMessageRule(@Nonnull String id, String path, boolean regex) {
suppressMessageRules.add(new SuppressMessageRule(id, path)); suppressMessageRules.add(new SuppressMessageRule(id, path, regex));
}
protected void addSuppressMessageRule(@Nonnull String id) {
suppressMessageRules.add(new SuppressMessageRule(id));
} }
@Override @Override
public boolean suppressMessageId(String path, String messageId) { public boolean isSuppressMessageId(String path, String messageId) {
String[] p = path.split("\\.");
for (SuppressMessageRule rule : suppressMessageRules) { for (SuppressMessageRule rule : suppressMessageRules) {
if (rule.matches(messageId, path)) { if (rule.matches(messageId, path, p)) {
return true; return true;
} }
} }
if (base != null) { if (base != null) {
return base.suppressMessageId(path, messageId); return base.isSuppressMessageId(path, messageId);
} else { } else {
return super.suppressMessageId(path, messageId); return super.isSuppressMessageId(path, messageId);
} }
} }

View File

@ -5,6 +5,8 @@ import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import javax.annotation.Nonnull;
import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor; import org.hl7.fhir.r5.utils.validation.IValidationPolicyAdvisor;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy; import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.Utilities; import org.hl7.fhir.utilities.Utilities;
@ -38,14 +40,19 @@ public class TextDrivenPolicyAdvisor extends RulesDrivenPolicyAdvisor {
return; return;
} }
if (line.startsWith("-")) { if (line.startsWith("-")) {
String s = line.substring(1).trim(); @Nonnull String s = line.substring(1).trim();
String id = s;
String path = null;
if (s.contains("@")) { if (s.contains("@")) {
id = s.substring(0, s.indexOf("@")); String id = s.substring(0, s.indexOf("@"));
path = s.substring(s.indexOf("@")+1); 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 { } else {
// ignore it for now // ignore it for now
} }

View File

@ -922,7 +922,7 @@ public class ValidationTests implements IEvaluationContext, IValidatorResourceFe
} }
@Override @Override
public boolean suppressMessageId(String path, String messageId) { public boolean isSuppressMessageId(String path, String messageId) {
return false; return false;
} }