Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-5027 ShaclSail logging #5029

Merged
merged 2 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,16 @@
import org.eclipse.rdf4j.sail.shacl.ast.paths.Path;
import org.eclipse.rdf4j.sail.shacl.ast.paths.SimplePath;
import org.eclipse.rdf4j.sail.shacl.results.ValidationResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Håvard Ottestad
*/
abstract class AbstractPairwisePlanNode implements PlanNode {

private static final Logger logger = LoggerFactory.getLogger(AbstractPairwisePlanNode.class);

private final SailConnection connection;
private final Resource[] dataGraph;
private final IRI predicate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.base.CoreDatatype;
import org.eclipse.rdf4j.model.datatypes.XMLDatatypeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Håvard Ottestad
*/
public class DatatypeFilter extends FilterPlanNode {

private static final Logger logger = LoggerFactory.getLogger(DatatypeFilter.class);

private final IRI datatype;
private final CoreDatatype.XSD xsdDatatype;
private StackTraceElement[] stackTrace;
Expand All @@ -37,17 +41,41 @@ public DatatypeFilter(PlanNode parent, IRI datatype) {
@Override
boolean checkTuple(Reference t) {
if (!(t.get().getValue().isLiteral())) {
logger.debug("Tuple rejected because it's not a literal. Tuple: {}", t);
return false;
}

Literal literal = (Literal) t.get().getValue();
if (xsdDatatype != null) {
if (literal.getCoreDatatype() == xsdDatatype) {
return XMLDatatypeUtil.isValidValue(literal.stringValue(), xsdDatatype);
boolean isValid = XMLDatatypeUtil.isValidValue(literal.stringValue(), xsdDatatype);
if (isValid) {
logger.trace(
"Tuple accepted because its literal value is valid according to the rules for the datatype in the XSD spec. Actual datatype: {}, Expected datatype: {}, Tuple: {}",
literal.getDatatype(), xsdDatatype, t);
} else {
logger.debug(
"Tuple rejected because its literal value is invalid according to the rules for the datatype in the XSD spec. Actual datatype: {}, Expected datatype: {}, Tuple: {}",
literal.getDatatype(), xsdDatatype, t);
}
return isValid;
}
logger.debug(
"Tuple rejected because literal's core datatype is not the expected datatype. Actual datatype: {}, Expected datatype: {}, Tuple: {}",
literal.getDatatype(), xsdDatatype, t);
return false;
} else {
return literal.getDatatype() == datatype || literal.getDatatype().equals(datatype);
boolean isEqual = literal.getDatatype() == datatype || literal.getDatatype().equals(datatype);
if (isEqual) {
logger.trace(
"Tuple accepted because literal's datatype is equal to the expected datatype. Actual datatype: {}, Expected datatype: {}, Tuple: {}",
literal.getDatatype(), datatype, t);
} else {
logger.debug(
"Tuple rejected because literal's datatype is not equal to the expected datatype. Actual datatype: {}, Expected datatype: {}, Tuple: {}",
literal.getDatatype(), datatype, t);
}
return isEqual;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,13 @@ boolean checkTuple(Reference t) {
t.set(map.apply(t.get(), bindingSet.next()));
} while (bindingSet.hasNext());
}
logger.trace("Tuple accepted because it matches the external query. Value: {}, Query: {}, Tuple: {}",
value, queryString, t);
return true;
}
}

logger.debug("Tuple rejected because it does not match the external query. Value: {}, Query: {}, Tuple: {}",
value, queryString, t);
return false;

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@

import org.apache.commons.text.StringEscapeUtils;
import org.eclipse.rdf4j.common.iteration.CloseableIteration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Håvard Ottestad
*/
public class GroupByCountFilter implements PlanNode {

private static final Logger logger = LoggerFactory.getLogger(GroupByCountFilter.class);

private final Function<Long, Boolean> filter;
PlanNode parent;
private boolean printed = false;
Expand Down Expand Up @@ -74,7 +78,13 @@ private void calculateNext() {
}

if (!filter.apply(count)) {
logger.debug(
"Tuple rejected because its count does not pass the filter. Actual count: {}, Tuple: {}",
count, this.next);
this.next = null;
} else {
logger.trace("Tuple accepted because its count passes the filter. Actual count: {}, Tuple: {}",
count, this.next);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@

import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.util.Literals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Håvard Ottestad
*/
public class LanguageInFilter extends FilterPlanNode {

private static final Logger logger = LoggerFactory.getLogger(LanguageInFilter.class);

private final List<String> languageRanges;
private final Set<String> lowerCaseLanguageIn;

Expand All @@ -37,17 +41,22 @@ public LanguageInFilter(PlanNode parent, Set<String> lowerCaseLanguageIn, List<S
@Override
boolean checkTuple(Reference t) {
if (!(t.get().getValue().isLiteral())) {
logger.debug("Tuple rejected because it's not a literal. Tuple: {}", t);
return false;
}

Optional<String> language = ((Literal) t.get().getValue()).getLanguage();
if (!language.isPresent()) {
if (language.isEmpty()) {
logger.debug("Tuple rejected because it does not have a language tag. Tuple: {}", t);
return false;
}

// early matching
boolean languageMatches = language.map(String::toLowerCase).filter(lowerCaseLanguageIn::contains).isPresent();
if (languageMatches) {
logger.trace(
"Tuple accepted because its language tag (toLowerCase()) is in the language set. Actual language: {}, Language set: {}, Tuple: {}",
language.get(), lowerCaseLanguageIn, t);
return true;
}

Expand All @@ -56,6 +65,9 @@ boolean checkTuple(Reference t) {

for (String languageRange : languageRanges) {
if (Literals.langMatches(langTag, languageRange)) {
logger.trace(
"Tuple accepted because its language tag matches the language range (BCP47). Actual language: {}, Language range: {}, Tuple: {}",
langTag, languageRange, t);
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@

import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.sail.shacl.ast.constraintcomponents.NodeKindConstraintComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Håvard Ottestad
*/
public class NodeKindFilter extends FilterPlanNode {

private static final Logger logger = LoggerFactory.getLogger(NodeKindFilter.class);

private final NodeKindConstraintComponent.NodeKind nodeKind;

public NodeKindFilter(PlanNode parent, NodeKindConstraintComponent.NodeKind nodeKind) {
Expand All @@ -32,28 +36,48 @@ public NodeKindFilter(PlanNode parent, NodeKindConstraintComponent.NodeKind node
boolean checkTuple(Reference t) {

Value value = t.get().getValue();
/*
* BlankNode(SHACL.BLANK_NODE), IRI(SHACL.IRI), Literal(SHACL.LITERAL), BlankNodeOrIRI(SHACL.BLANK_NODE_OR_IRI),
* BlankNodeOrLiteral(SHACL.BLANK_NODE_OR_LITERAL), IRIOrLiteral(SHACL.IRI_OR_LITERAL),
*/

switch (nodeKind) {
case IRI:
return value.isIRI();
if (value.isIRI()) {
logger.trace("Tuple accepted because its value is an IRI. Tuple: {}", t);
return true;
}
break;
case Literal:
return value.isLiteral();
if (value.isLiteral()) {
logger.trace("Tuple accepted because its value is a Literal. Tuple: {}", t);
return true;
}
break;
case BlankNode:
return value.isBNode();
if (value.isBNode()) {
logger.trace("Tuple accepted because its value is a BlankNode. Tuple: {}", t);
return true;
}
break;
case IRIOrLiteral:
return value.isIRI() || value.isLiteral();
if (value.isIRI() || value.isLiteral()) {
logger.trace("Tuple accepted because its value is an IRI or Literal. Tuple: {}", t);
return true;
}
break;
case BlankNodeOrIRI:
return value.isBNode() || value.isIRI();
if (value.isBNode() || value.isIRI()) {
logger.trace("Tuple accepted because its value is a BlankNode or IRI. Tuple: {}", t);
return true;
}
break;
case BlankNodeOrLiteral:
return value.isBNode() || value.isLiteral();
if (value.isBNode() || value.isLiteral()) {
logger.trace("Tuple accepted because its value is a BlankNode or Literal. Tuple: {}", t);
return true;
}
break;
}

throw new IllegalStateException("Unknown nodeKind");

logger.debug("Tuple rejected because its value does not match the expected node kind. Tuple: {}", t);
return false;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,55 +15,65 @@
import java.util.regex.Pattern;

import org.eclipse.rdf4j.model.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* @author Håvard Ottestad
*/
public class PatternFilter extends FilterPlanNode {

private static final Logger logger = LoggerFactory.getLogger(PatternFilter.class);

private final Pattern pattern;

public PatternFilter(PlanNode parent, String pattern, String flags) {
super(parent);
if (flags != null && !flags.isEmpty()) {

int flag = 0b0;

if (flags.contains("i")) {
flag = flag | Pattern.CASE_INSENSITIVE;
logger.trace("PatternFilter constructed with case insensitive flag");
}

if (flags.contains("d")) {
flag = flag | Pattern.UNIX_LINES;
logger.trace("PatternFilter constructed with UNIX lines flag");
}

if (flags.contains("m")) {
flag = flag | Pattern.MULTILINE;
logger.trace("PatternFilter constructed with multiline flag");
}

if (flags.contains("s")) {
flag = flag | Pattern.DOTALL;
logger.trace("PatternFilter constructed with dotall flag");
}

if (flags.contains("u")) {
flag = flag | Pattern.UNICODE_CASE;
logger.trace("PatternFilter constructed with unicode case flag");
}

if (flags.contains("x")) {
flag = flag | Pattern.COMMENTS;
logger.trace("PatternFilter constructed with comments flag");
}

if (flags.contains("U")) {
flag = flag | Pattern.UNICODE_CHARACTER_CLASS;
logger.trace("PatternFilter constructed with unicode character class flag");
}

this.pattern = Pattern.compile(pattern, flag);
logger.trace("PatternFilter constructed with pattern: {} and flags: {}", pattern, flags);

} else {
this.pattern = Pattern.compile(pattern);

logger.trace("PatternFilter constructed with pattern: {} and no flags", pattern);
}

}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ public static PlanNode getInstance(PlanNode parent, boolean compress) {
if (parent.isGuaranteedEmpty()) {
return parent;
}

if (parent instanceof Unique && (!compress || ((Unique) parent).compress == compress)) {
return parent;
}

return new Unique(parent, compress);
}

Expand Down
Loading