Code optimization and polishing.
This commit is contained in:
parent
7be1dbe493
commit
a4c7c33907
|
@ -2,18 +2,16 @@ package eu.dnetlib.validator2.engine;
|
||||||
|
|
||||||
public class RuleEngine {
|
public class RuleEngine {
|
||||||
|
|
||||||
public static <T, R extends Rule<T>> void applyAndReport(R rule, T t, Reporter<T, R> reporter) {
|
public static <T, R extends Rule<T>> void applyAndReport(R rule, T t, Reporter<T, R> reporter) throws IllegalArgumentException
|
||||||
|
{
|
||||||
if (reporter == null) throw new IllegalArgumentException("Reporter cannot be null");
|
if (reporter == null) throw new IllegalArgumentException("Reporter cannot be null");
|
||||||
if (rule == null) throw new IllegalArgumentException("Rule cannot be null");
|
if (rule == null) throw new IllegalArgumentException("Rule cannot be null");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(rule.test(t)) {
|
if ( rule.test(t) )
|
||||||
reporter.reportSuccessFor(rule, t);
|
reporter.reportSuccessFor(rule, t);
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
reporter.reportFailureFor(rule, t);
|
reporter.reportFailureFor(rule, t);
|
||||||
}
|
|
||||||
} catch (Throwable throwable) {
|
} catch (Throwable throwable) {
|
||||||
reporter.reportErrorFor(rule, t, throwable);
|
reporter.reportErrorFor(rule, t, throwable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,6 @@ public class XPathExpressionHelper {
|
||||||
if ( logger.isTraceEnabled() )
|
if ( logger.isTraceEnabled() )
|
||||||
logger.trace("Compiling {}", s);
|
logger.trace("Compiling {}", s);
|
||||||
XPathExpression expr = XPATH.compile(s);
|
XPathExpression expr = XPATH.compile(s);
|
||||||
if ( logger.isTraceEnabled() )
|
|
||||||
logger.trace("Compiled {} = {}", s, expr);
|
|
||||||
return expr;
|
return expr;
|
||||||
} catch (XPathExpressionException e) {
|
} catch (XPathExpressionException e) {
|
||||||
logger.error("Compilation failure", e);
|
logger.error("Compilation failure", e);
|
||||||
|
|
|
@ -436,12 +436,13 @@ class ElementSpecCompiler {
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Document doc) throws RuleEvaluationException {
|
public boolean test(Document doc) throws RuleEvaluationException {
|
||||||
GuidelineEvaluation guidelineEvaluation = runtimeInfo.get();
|
GuidelineEvaluation guidelineEvaluation = runtimeInfo.get();
|
||||||
String thisId = getContext().getIdProperty().getValue();
|
XMLContext context = getContext();
|
||||||
|
String thisId = context.getIdProperty().getValue();
|
||||||
|
|
||||||
if (isApplicable(this, guidelineEvaluation).test(doc)) {
|
if (isApplicable(this, guidelineEvaluation).test(doc)) {
|
||||||
try {
|
try {
|
||||||
logger.debug("Applying {}", thisId);
|
logger.debug("Applying {}", thisId);
|
||||||
NodeList nodes = getContext().getXPathExpressionProperty().evaluate(doc);
|
NodeList nodes = context.getXPathExpressionProperty().evaluate(doc);
|
||||||
boolean result = predicate.test(nodes);
|
boolean result = predicate.test(nodes);
|
||||||
if (result) {
|
if (result) {
|
||||||
logger.debug("Setting node list of this rule {}", thisId);
|
logger.debug("Setting node list of this rule {}", thisId);
|
||||||
|
|
|
@ -47,27 +47,27 @@ class GuidelineEvaluation {
|
||||||
|
|
||||||
logger.debug("Evaluating " + rules);
|
logger.debug("Evaluating " + rules);
|
||||||
|
|
||||||
for (SyntheticRule<Document> rule: rules) {
|
for ( SyntheticRule<Document> rule: rules ) {
|
||||||
|
|
||||||
String id = rule.getContext().getIdProperty().getValue();
|
String id = rule.getContext().getIdProperty().getValue();
|
||||||
|
|
||||||
RuleEngine.applyAndReport(rule, doc, reporter);
|
RuleEngine.applyAndReport(rule, doc, reporter);
|
||||||
|
|
||||||
Status status = diagnostics.getLastReportedStatus();
|
Status status = diagnostics.getLastReportedStatus();
|
||||||
if (status == Status.ERROR) {
|
if ( status == Status.ERROR ) {
|
||||||
// fail fast in case of errors (no reason to proceed, since results may be rubbish)
|
// fail fast in case of errors (no reason to proceed, since results may be rubbish)
|
||||||
return StandardResult.forError(diagnostics.getLastReportedError().getMessage());
|
return StandardResult.forError(diagnostics.getLastReportedError().getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == Status.SUCCESS && getRequirementLevelOf(id) == RequirementLevel.NOT_APPLICABLE) {
|
if ( status == Status.SUCCESS && getRequirementLevelOf(id) == RequirementLevel.NOT_APPLICABLE ) {
|
||||||
// Report the non-applicability of a rule as a warning
|
// Report the non-applicability of a rule as a warning
|
||||||
// The check for both status and non-applicable requirement level is redundant
|
// The check for both status and non-applicable requirement level is redundant
|
||||||
// (non-applicable rules always succeed), yet it is more clear hopefully.
|
// (non-applicable rules always succeed), yet it is more clear, hopefully.
|
||||||
logger.warn("Non-applicable: " + rule);
|
logger.warn("Non-applicable: " + rule);
|
||||||
warnings.add(synthesizeFailureMessage(rule));
|
warnings.add(synthesizeFailureMessage(rule));
|
||||||
}
|
}
|
||||||
else if (status == Status.FAILURE) {
|
else if ( status == Status.FAILURE ) {
|
||||||
if (getRequirementLevelOf(id) == RequirementLevel.MANDATORY) {
|
if ( getRequirementLevelOf(id) == RequirementLevel.MANDATORY ) {
|
||||||
// A mandatory rule has failed, yet we don't know whether we should report is as such.
|
// A mandatory rule has failed, yet we don't know whether we should report is as such.
|
||||||
|
|
||||||
// Let's check the parent of the rule
|
// Let's check the parent of the rule
|
||||||
|
@ -78,8 +78,7 @@ class GuidelineEvaluation {
|
||||||
logger.error("Fail fast for root failure: " + rule);
|
logger.error("Fail fast for root failure: " + rule);
|
||||||
errors.add(synthesizeFailureMessage(rule));
|
errors.add(synthesizeFailureMessage(rule));
|
||||||
return StandardResult.forFailure(warnings, errors);
|
return StandardResult.forFailure(warnings, errors);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// The current rule has a parent/ancestor which:
|
// The current rule has a parent/ancestor which:
|
||||||
// (a) is non-mandatory or
|
// (a) is non-mandatory or
|
||||||
// (b) it was successful.
|
// (b) it was successful.
|
||||||
|
@ -87,8 +86,7 @@ class GuidelineEvaluation {
|
||||||
logger.warn("Mandatory failure: " + rule);
|
logger.warn("Mandatory failure: " + rule);
|
||||||
warnings.add(synthesizeFailureMessage(rule));
|
warnings.add(synthesizeFailureMessage(rule));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// This is a warning: a non-mandatory rule has failed.
|
// This is a warning: a non-mandatory rule has failed.
|
||||||
// Note that MA rules are treated as non-mandatory.
|
// Note that MA rules are treated as non-mandatory.
|
||||||
// We let the evaluation loop proceed.
|
// We let the evaluation loop proceed.
|
||||||
|
@ -99,7 +97,7 @@ class GuidelineEvaluation {
|
||||||
}
|
}
|
||||||
|
|
||||||
int returnedWeight = weight;
|
int returnedWeight = weight;
|
||||||
if (rules.size() == warnings.size()) {
|
if ( rules.size() == warnings.size() ) {
|
||||||
// TODO: I think this is the desired behavior, but we need to get confirmation for this.
|
// TODO: I think this is the desired behavior, but we need to get confirmation for this.
|
||||||
// All rules have failed, but with warnings (thus being either optional or recommended).
|
// All rules have failed, but with warnings (thus being either optional or recommended).
|
||||||
// This indicates a success with 0 weight.
|
// This indicates a success with 0 weight.
|
||||||
|
@ -109,12 +107,10 @@ class GuidelineEvaluation {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String synthesizeFailureMessage(Rule<Document> rule) {
|
private String synthesizeFailureMessage(Rule<Document> rule) {
|
||||||
|
|
||||||
return subjectId + ": rule " + Helper.stringify(rule) + " has failed";
|
return subjectId + ": rule " + Helper.stringify(rule) + " has failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
private String synthesizeNotApplicableMessage(Rule<Document> rule) {
|
private String synthesizeNotApplicableMessage(Rule<Document> rule) {
|
||||||
|
|
||||||
return subjectId + ": rule " + Helper.stringify(rule) + " is not applicable";
|
return subjectId + ": rule " + Helper.stringify(rule) + " is not applicable";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -386,6 +386,7 @@ class F2_01M_SPEC extends AbstractGuideline<Document> {
|
||||||
// TODO: iterate over results and build one Guideline.Result
|
// TODO: iterate over results and build one Guideline.Result
|
||||||
try {
|
try {
|
||||||
XMLApplicationProfile.ValidationResult res_F = profile.validate(id, t);
|
XMLApplicationProfile.ValidationResult res_F = profile.validate(id, t);
|
||||||
|
Map<String, Guideline.Result> results = res_F.results();
|
||||||
|
|
||||||
// Get actual score and not (%) to incorporate to FAIR score
|
// Get actual score and not (%) to incorporate to FAIR score
|
||||||
final int MaxScoreF2_01M_SPEC = (int) ((res_F.score()*getWeight())/100);
|
final int MaxScoreF2_01M_SPEC = (int) ((res_F.score()*getWeight())/100);
|
||||||
|
@ -397,19 +398,23 @@ class F2_01M_SPEC extends AbstractGuideline<Document> {
|
||||||
List<String> warnings2 = new ArrayList<>();
|
List<String> warnings2 = new ArrayList<>();
|
||||||
List<String> errors2 = new ArrayList<>();
|
List<String> errors2 = new ArrayList<>();
|
||||||
int score = 0;
|
int score = 0;
|
||||||
|
for (Map.Entry<String, Guideline.Result> entry : results.entrySet()) {
|
||||||
for (Map.Entry entry : res_F.results().entrySet()) {
|
String key = entry.getKey();
|
||||||
if (res_F.results().get(entry.getKey()).warnings().toString().length() > 2) {
|
String warningsStr = results.get(key).warnings().toString();
|
||||||
warnings2.add(res_F.results().get(entry.getKey()).warnings().toString());
|
String errorsStr = results.get(key).errors().toString();
|
||||||
|
if ( warningsStr.length() > 2 ) {
|
||||||
|
warnings2.add(warningsStr);
|
||||||
}
|
}
|
||||||
if (res_F.results().get(entry.getKey()).errors().toString().length() > 2) {
|
if ( errorsStr.length() > 2 ) {
|
||||||
errors2.add(res_F.results().get(entry.getKey()).errors().toString());
|
errors2.add(errorsStr);
|
||||||
}
|
}
|
||||||
if (entry.getValue().toString().contains("SUCCESS")) {
|
if (entry.getValue().toString().contains("SUCCESS")) {
|
||||||
score += 2;
|
score += 2;
|
||||||
}
|
}
|
||||||
logger.debug(String.valueOf(res_F.results().get(entry.getKey()).warnings().getClass()));
|
if ( logger.isTraceEnabled() ) {
|
||||||
logger.debug(String.valueOf(warnings2.getClass()));
|
logger.trace(String.valueOf(results.get(key).warnings().getClass()));
|
||||||
|
logger.trace(String.valueOf(warnings2.getClass()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -470,7 +475,7 @@ class F3_01M_SPEC extends AbstractGuideline<Document> {
|
||||||
try {
|
try {
|
||||||
// System.out.println("\nMetadata includes the identifier for the data");
|
// System.out.println("\nMetadata includes the identifier for the data");
|
||||||
XMLApplicationProfile.ValidationResult res_F = profile.validate(id, t);
|
XMLApplicationProfile.ValidationResult res_F = profile.validate(id, t);
|
||||||
Map<String, Result> results = res_F.results();
|
Map<String, Guideline.Result> results = res_F.results();
|
||||||
// int MaxScoreF3_01M_SPEC = (int) ((res_F.score()*getWeight())/100);
|
// int MaxScoreF3_01M_SPEC = (int) ((res_F.score()*getWeight())/100);
|
||||||
|
|
||||||
int MaxScoreF3_01M_SPEC;
|
int MaxScoreF3_01M_SPEC;
|
||||||
|
@ -483,12 +488,15 @@ class F3_01M_SPEC extends AbstractGuideline<Document> {
|
||||||
|
|
||||||
ArrayList<String> warnings2 = new ArrayList<>();
|
ArrayList<String> warnings2 = new ArrayList<>();
|
||||||
ArrayList<String> errors2 = new ArrayList<>();
|
ArrayList<String> errors2 = new ArrayList<>();
|
||||||
for (Map.Entry entry : res_F.results().entrySet()) {
|
for (Map.Entry<String, Guideline.Result> entry : results.entrySet()) {
|
||||||
if (res_F.results().get(entry.getKey()).warnings().toString().length() > 2) {
|
String key = entry.getKey();
|
||||||
warnings2.add(res_F.results().get(entry.getKey()).warnings().toString());
|
String warningsStr = results.get(key).warnings().toString();
|
||||||
|
String errorsStr = results.get(key).errors().toString();
|
||||||
|
if ( warningsStr.length() > 2 ) {
|
||||||
|
warnings2.add(warningsStr);
|
||||||
}
|
}
|
||||||
if (res_F.results().get(entry.getKey()).errors().toString().length() > 2) {
|
if ( errorsStr.length() > 2 ) {
|
||||||
errors2.add(res_F.results().get(entry.getKey()).errors().toString());
|
errors2.add(errorsStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,9 +552,9 @@ class I2_01M_SPEC extends AbstractGuideline<Document> {
|
||||||
|
|
||||||
// TODO: iterate over results and build one Guideline.Result
|
// TODO: iterate over results and build one Guideline.Result
|
||||||
try {
|
try {
|
||||||
logger.debug("\nMetadata uses FAIR-compliant vocabularies");
|
logger.debug("Metadata uses FAIR-compliant vocabularies");
|
||||||
XMLApplicationProfile.ValidationResult res_F = profile.validate(id, t);
|
XMLApplicationProfile.ValidationResult res_F = profile.validate(id, t);
|
||||||
Map<String, Result> results = res_F.results();
|
Map<String, Guideline.Result> results = res_F.results();
|
||||||
// int MaxScoreI2_01M_SPEC = (int) ((res_F.score()*getWeight())/100);
|
// int MaxScoreI2_01M_SPEC = (int) ((res_F.score()*getWeight())/100);
|
||||||
|
|
||||||
int MaxScoreI2_01M_SPEC;
|
int MaxScoreI2_01M_SPEC;
|
||||||
|
@ -559,12 +567,15 @@ class I2_01M_SPEC extends AbstractGuideline<Document> {
|
||||||
|
|
||||||
ArrayList<String> warnings2 = new ArrayList<>();
|
ArrayList<String> warnings2 = new ArrayList<>();
|
||||||
ArrayList<String> errors2 = new ArrayList<>();
|
ArrayList<String> errors2 = new ArrayList<>();
|
||||||
for (Map.Entry entry : res_F.results().entrySet()) {
|
for (Map.Entry<String, Guideline.Result> entry : results.entrySet()) {
|
||||||
if (res_F.results().get(entry.getKey()).warnings().toString().length() > 2) {
|
String key = entry.getKey();
|
||||||
warnings2.add(res_F.results().get(entry.getKey()).warnings().toString());
|
String warningsStr = results.get(key).warnings().toString();
|
||||||
|
String errorsStr = results.get(key).errors().toString();
|
||||||
|
if ( warningsStr.length() > 2 ) {
|
||||||
|
warnings2.add(warningsStr);
|
||||||
}
|
}
|
||||||
if (res_F.results().get(entry.getKey()).errors().toString().length() > 2) {
|
if ( errorsStr.length() > 2 ) {
|
||||||
errors2.add(res_F.results().get(entry.getKey()).errors().toString());
|
errors2.add(errorsStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,18 +635,21 @@ class R1_01M_SPEC extends AbstractGuideline<Document> {
|
||||||
try {
|
try {
|
||||||
// System.out.println("\nPlurality of accurate and relevant attributes are provided to allow reuse");
|
// System.out.println("\nPlurality of accurate and relevant attributes are provided to allow reuse");
|
||||||
XMLApplicationProfile.ValidationResult res_F = profile.validate(id, t);
|
XMLApplicationProfile.ValidationResult res_F = profile.validate(id, t);
|
||||||
Map<String, Result> results = res_F.results();
|
Map<String, Guideline.Result> results = res_F.results();
|
||||||
int MaxScoreR1_01M_SPEC = (int) ((res_F.score()*getWeight())/100);
|
int MaxScoreR1_01M_SPEC = (int) ((res_F.score()*getWeight())/100);
|
||||||
|
|
||||||
ArrayList<String> warnings2 = new ArrayList<>();
|
ArrayList<String> warnings2 = new ArrayList<>();
|
||||||
ArrayList<String> errors2 = new ArrayList<>();
|
ArrayList<String> errors2 = new ArrayList<>();
|
||||||
int score = 0;
|
int score = 0;
|
||||||
for (Map.Entry entry : res_F.results().entrySet()) {
|
for (Map.Entry<String, Guideline.Result> entry : results.entrySet()) {
|
||||||
if (res_F.results().get(entry.getKey()).warnings().toString().length() > 2) {
|
String key = entry.getKey();
|
||||||
warnings2.add(res_F.results().get(entry.getKey()).warnings().toString());
|
String warningsStr = results.get(key).warnings().toString();
|
||||||
|
String errorsStr = results.get(key).errors().toString();
|
||||||
|
if ( warningsStr.length() > 2 ) {
|
||||||
|
warnings2.add(warningsStr);
|
||||||
}
|
}
|
||||||
if (res_F.results().get(entry.getKey()).errors().toString().length() > 2) {
|
if ( errorsStr.length() > 2 ) {
|
||||||
errors2.add(res_F.results().get(entry.getKey()).errors().toString());
|
errors2.add(errorsStr);
|
||||||
}
|
}
|
||||||
if (entry.getValue().toString().contains("SUCCESS")) {
|
if (entry.getValue().toString().contains("SUCCESS")) {
|
||||||
score += 3;
|
score += 3;
|
||||||
|
@ -698,19 +712,21 @@ class R1_2_01M_SPEC extends AbstractGuideline<Document> {
|
||||||
try {
|
try {
|
||||||
// System.out.println("\nMetadata includes provenance information according to a cross-community language");
|
// System.out.println("\nMetadata includes provenance information according to a cross-community language");
|
||||||
XMLApplicationProfile.ValidationResult res_F = profile.validate(id, t);
|
XMLApplicationProfile.ValidationResult res_F = profile.validate(id, t);
|
||||||
Map<String, Result> results = res_F.results();
|
Map<String, Guideline.Result> results = res_F.results();
|
||||||
int MaxScoreR1_2_01M_SPEC = (int) ((res_F.score()*getWeight())/100);
|
int MaxScoreR1_2_01M_SPEC = (int) ((res_F.score()*getWeight())/100);
|
||||||
|
|
||||||
|
|
||||||
ArrayList<String> warnings2 = new ArrayList<>();
|
ArrayList<String> warnings2 = new ArrayList<>();
|
||||||
ArrayList<String> errors2 = new ArrayList<>();
|
ArrayList<String> errors2 = new ArrayList<>();
|
||||||
int score = 0;
|
int score = 0;
|
||||||
for (Map.Entry entry : res_F.results().entrySet()) {
|
for (Map.Entry<String, Guideline.Result> entry : results.entrySet()) {
|
||||||
if (res_F.results().get(entry.getKey()).warnings().toString().length() > 2) {
|
String key = entry.getKey();
|
||||||
warnings2.add(res_F.results().get(entry.getKey()).warnings().toString());
|
String warningsStr = results.get(key).warnings().toString();
|
||||||
|
String errorsStr = results.get(key).errors().toString();
|
||||||
|
if ( warningsStr.length() > 2 ) {
|
||||||
|
warnings2.add(warningsStr);
|
||||||
}
|
}
|
||||||
if (res_F.results().get(entry.getKey()).errors().toString().length() > 2) {
|
if ( errorsStr.length() > 2 ) {
|
||||||
errors2.add(res_F.results().get(entry.getKey()).errors().toString());
|
errors2.add(errorsStr);
|
||||||
}
|
}
|
||||||
if (entry.getValue().toString().contains("SUCCESS")) {
|
if (entry.getValue().toString().contains("SUCCESS")) {
|
||||||
score += 3;
|
score += 3;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package eu.dnetlib.validator2.engine
|
package eu.dnetlib.validator2.engine
|
||||||
|
|
||||||
import eu.dnetlib.validator2.engine.Helper
|
|
||||||
import groovy.xml.DOMBuilder
|
import groovy.xml.DOMBuilder
|
||||||
import groovy.xml.FactorySupport
|
import groovy.xml.FactorySupport
|
||||||
import org.w3c.dom.Document
|
import org.w3c.dom.Document
|
||||||
|
@ -31,8 +31,8 @@ class XMLHelper {
|
||||||
int bufferSize,
|
int bufferSize,
|
||||||
Predicate<ZipEntry> filter,
|
Predicate<ZipEntry> filter,
|
||||||
BiConsumer < String, Document > documentConsumer) {
|
BiConsumer < String, Document > documentConsumer) {
|
||||||
if (documentConsumer) {
|
if (documentConsumer)
|
||||||
|
{
|
||||||
DocumentBuilderFactory factory = FactorySupport.createDocumentBuilderFactory()
|
DocumentBuilderFactory factory = FactorySupport.createDocumentBuilderFactory()
|
||||||
factory.setNamespaceAware(true)
|
factory.setNamespaceAware(true)
|
||||||
factory.setValidating(false)
|
factory.setValidating(false)
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class Test_FAIR {
|
||||||
"src/test/resources/openaireguidelinesV3/cris.vtt.fi/02_data.xml",
|
"src/test/resources/openaireguidelinesV3/cris.vtt.fi/02_data.xml",
|
||||||
"src/test/resources/openaireguidelinesV3/cris.vtt.fi/04_data.xml",
|
"src/test/resources/openaireguidelinesV3/cris.vtt.fi/04_data.xml",
|
||||||
"src/test/resources/openaireguidelinesV3/cris.vtt.fi/03_data.xml",
|
"src/test/resources/openaireguidelinesV3/cris.vtt.fi/03_data.xml",
|
||||||
"src/test/resources/openaireguidelinesV4/01_gv4.xml"
|
//"src/test/resources/openaireguidelinesV4/01_gv4.xml" // This file does not exist!
|
||||||
};
|
};
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
Loading…
Reference in New Issue