From 1ac18bfd4db81c69f8eff4cd3895d814b3f440a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Ottestad?= Date: Thu, 11 Jan 2024 13:24:02 +0100 Subject: [PATCH] GH-4867 log exceptions as warnings during parsing and validation of SHACL shapes --- .../rdf4j/sail/shacl/ShaclSailConnection.java | 1 + .../rdf4j/sail/shacl/ShaclValidator.java | 6 ++ .../sail/shacl/ShapeValidationContainer.java | 1 + .../eclipse/rdf4j/sail/shacl/ast/Shape.java | 5 +- .../results/lazy/LazyValidationReport.java | 62 ++++++++++++------- 5 files changed, 51 insertions(+), 24 deletions(-) diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java index 779bdd7472e..7576c9ec48a 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclSailConnection.java @@ -1145,6 +1145,7 @@ public ValidationResultIterator performValidation() { sail.getEffectiveValidationResultsLimitPerConstraint()); return validationResults; } catch (Exception e) { + logger.warn("Error validating SHACL Shape {}", shape.getId(), e); throw new SailException("Error validating SHACL Shape " + shape.getId() + "\n" + shape, e); } finally { handlePostLogging(before, validationResults); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclValidator.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclValidator.java index 714fa148544..ca2cff3c05f 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclValidator.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShaclValidator.java @@ -77,6 +77,9 @@ public static ValidationReport validate(Sail dataRepo, Sail shapesRepo) { } shapesConnection.commit(); + } catch (Exception e) { + logger.warn("Failed to read shapes", e); + throw e; } try (SailConnection dataRepoConnection = dataRepo.getConnection()) { @@ -95,6 +98,9 @@ public static ValidationReport validate(Sail dataRepo, Sail shapesRepo) { return performValidation(shapes, new ConnectionsGroup(verySimpleRdfsBackwardsChainingConnection, null, null, null, new Stats(), () -> reasoner, new ShaclSailConnection.Settings(true, true, true, IsolationLevels.NONE), true)); + } catch (Exception e) { + logger.warn("Failed to validate shapes", e); + throw e; } } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShapeValidationContainer.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShapeValidationContainer.java index ada79d21538..55f6e0d51b9 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShapeValidationContainer.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ShapeValidationContainer.java @@ -77,6 +77,7 @@ public ValidationResultIterator performValidation() { validationResults = new ValidationResultIterator(iterator, effectiveValidationResultsLimitPerConstraint); return validationResults; } catch (Exception e) { + logger.warn("Error validating SHACL Shape {}", shape.getId(), e); throw new SailException("Error validating SHACL Shape " + shape.getId() + "\n" + shape, e); } finally { handlePostLogging(before, validationResults); diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/Shape.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/Shape.java index 7280acd8067..0bd3af408bd 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/Shape.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/ast/Shape.java @@ -448,9 +448,10 @@ public PlanNode generatePlans(ConnectionsGroup connectionsGroup, ValidationSetti } } else { - throw new ShaclUnsupportedException("Unkown validation approach: " + validationApproach); + throw new ShaclUnsupportedException("Unknown validation approach: " + validationApproach); } } catch (RuntimeException e) { + logger.warn("Error processing SHACL Shape {}", id, e); throw new SailException("Error processing SHACL Shape " + id + "\n" + this, e); } @@ -707,6 +708,7 @@ public static List getShapesInContext(ShapeSource shapeSource, try { return new ShaclProperties(r, shapeSourceWithContext); } catch (Exception e) { + logger.warn("Error parsing shape {}", r, e); throw new ShaclShapeParsingException(e, r); } }) @@ -719,6 +721,7 @@ public static List getShapesInContext(ShapeSource shapeSource, } throw new ShaclShapeParsingException("Unknown shape type", p.getId()); } catch (Exception e) { + logger.warn("Error parsing shape {}", p.getId(), e); if (e instanceof ShaclShapeParsingException) { throw e; } diff --git a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/lazy/LazyValidationReport.java b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/lazy/LazyValidationReport.java index 0bd778273d4..53b4dd3e520 100644 --- a/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/lazy/LazyValidationReport.java +++ b/core/sail/shacl/src/main/java/org/eclipse/rdf4j/sail/shacl/results/lazy/LazyValidationReport.java @@ -35,8 +35,11 @@ import org.eclipse.rdf4j.rio.Rio; import org.eclipse.rdf4j.rio.WriterConfig; import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings; +import org.eclipse.rdf4j.sail.shacl.ShaclSailConnection; import org.eclipse.rdf4j.sail.shacl.results.ValidationReport; import org.eclipse.rdf4j.sail.shacl.results.ValidationResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A ValidationReport that will defer calculating any ValidationResults until the user asks for them @@ -44,6 +47,8 @@ @InternalUseOnly public class LazyValidationReport extends ValidationReport { + private static final Logger logger = LoggerFactory.getLogger(LazyValidationReport.class); + private List validationResultIterators; private final long limit; @@ -55,44 +60,55 @@ public LazyValidationReport(List validationResultItera } private void evaluateLazyAspect() { - if (validationResultIterators != null) { - long counter = 0; - for (ValidationResultIterator validationResultIterator : validationResultIterators) { - while (validationResultIterator.hasNext()) { - if (limit >= 0 && counter >= limit) { - truncated = true; - break; + try { + if (validationResultIterators != null) { + long counter = 0; + for (ValidationResultIterator validationResultIterator : validationResultIterators) { + while (validationResultIterator.hasNext()) { + if (limit >= 0 && counter >= limit) { + truncated = true; + break; + } + counter++; + + validationResult.add(validationResultIterator.next()); } - counter++; - validationResult.add(validationResultIterator.next()); + this.conforms = conforms && validationResultIterator.conforms(); + this.truncated = truncated || validationResultIterator.isTruncated(); } - this.conforms = conforms && validationResultIterator.conforms(); - this.truncated = truncated || validationResultIterator.isTruncated(); - } - - validationResultIterators = null; + validationResultIterators = null; + } + } catch (Exception e) { + logger.warn("Error evaluating lazy validation report", e); + throw e; } } public Model asModel(Model model) { - evaluateLazyAspect(); + try { + evaluateLazyAspect(); + + model.add(getId(), SHACL.CONFORMS, literal(conforms)); + model.add(getId(), RDF.TYPE, SHACL.VALIDATION_REPORT); + model.add(getId(), RDF4J.TRUNCATED, BooleanLiteral.valueOf(truncated)); - model.add(getId(), SHACL.CONFORMS, literal(conforms)); - model.add(getId(), RDF.TYPE, SHACL.VALIDATION_REPORT); - model.add(getId(), RDF4J.TRUNCATED, BooleanLiteral.valueOf(truncated)); + HashSet rdfListDedupe = new HashSet<>(); - HashSet rdfListDedupe = new HashSet<>(); + for (ValidationResult result : validationResult) { + model.add(getId(), SHACL.RESULT, result.getId()); + result.asModel(model, rdfListDedupe); + } - for (ValidationResult result : validationResult) { - model.add(getId(), SHACL.RESULT, result.getId()); - result.asModel(model, rdfListDedupe); + return model; + } catch (Exception e) { + logger.warn("Error converting validation report to model", e); + throw e; } - return model; } public Model asModel() {