Skip to content

Commit

Permalink
apacheGH-1636: add support for semantic actions
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Prud'hommeaux committed Dec 1, 2022
1 parent 8a70bcb commit ecffbee
Show file tree
Hide file tree
Showing 46 changed files with 1,048 additions and 290 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class TestManifest {
/** <p>Required functionality for execution of this test</p> */
public static final Property requires = m_model.createProperty( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#requires" );

/** <p>The test statusThe expected outcome</p> */
/** <p>The expected outcome</p> */
public static final Property result = m_model.createProperty( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#result" );

/** <p>Action to perform</p> */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ private void parseOneIncludesList(Resource r)
}
}

private static Resource getResource(Resource r, Property p)
public static Resource getResource(Resource r, Property p)
{
if ( r == null )
return null ;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class TestManifest {
/** <p>The namespace of the vocabulary as a resource</p> */
public static final Resource NAMESPACE = m_model.createResource( NS );

/** <p>The test statusThe expected outcome</p> */
/** <p>The expected outcome</p> */
public static final Property result = m_model.createProperty( "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#result" );

/** <p>Action to perform</p> */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import org.apache.jena.shex.sys.ShexLib;
import org.apache.jena.vocabulary.RDF;

/** Validate based on building a shap map in the code. */
/** Validate based on building a shape map in the code. */
public class Shex03_validate {
static { LogCtl.setLogging(); }

Expand Down
2 changes: 1 addition & 1 deletion jena-shex/examples/schema.shex
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ START = @<#shape2>

<#shape2> IRI {
:property [123 456] ;
}
}
84 changes: 55 additions & 29 deletions jena-shex/shexc/shex.jj
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ void start() : { }
{ finishStartClause(); }
}

void startActions() : {}
void startActions() : {SemAct semAct;}
{
(codeDecl())+
(semAct = codeDecl() { semActs(semAct, token.beginLine, token.beginColumn); })+
}

void statement() : {}
Expand Down Expand Up @@ -170,9 +170,9 @@ void shapeAtom() : { int idx; }
{
{ idx = startShapeAtom(); }
// No literals-as-subjects.
( nonLitNodeConstraint() (shapeOrRef())?
| litNodeConstraint()
| shapeOrRef() (nonLitNodeConstraint())?
( nonLitOutlineNodeConstraint() (shapeOrRef())?
| litOutlineNodeConstraint()
| shapeOrRef() (nonLitOutlineNodeConstraint())?
| <LPAREN> shapeExpression() <RPAREN>
| <DOT> { shapeAtomDOT(); }
)
Expand Down Expand Up @@ -224,9 +224,9 @@ void inlineShapeAtom() : { int idx; }
{
{ idx = startInlineShapeAtom(); }
// No literals-as-subjects.
( nonLitNodeConstraint() (inlineShapeOrRef())?
| litNodeConstraint()
| inlineShapeOrRef() (nonLitNodeConstraint())?
( nonLitInlineNodeConstraint() (inlineShapeOrRef())?
| litInlineNodeConstraint()
| inlineShapeOrRef() (nonLitInlineNodeConstraint())?
| <LPAREN> shapeExpression() <RPAREN>
| <DOT> { shapeAtomDOT(); }
)
Expand Down Expand Up @@ -254,8 +254,20 @@ void shapeRef() : { Token t ; Node ref; }
{ shapeReference(ref); }
}

void litNodeConstraint() : { String str; Token t; int idx; } {
void litInlineNodeConstraint() : { int idx; } {
{ idx = startLiteralNodeConstraint(token.beginLine, token.beginColumn); }
litNodeConstraint()
{ finishLiteralNodeConstraint(null, idx, token.beginLine, token.beginColumn); }
}

void litOutlineNodeConstraint() : { int idx; List<SemAct> semActs; } {
{ idx = startLiteralNodeConstraint(token.beginLine, token.beginColumn); }
litNodeConstraint()
semActs = semanticActions()
{ finishLiteralNodeConstraint(semActs, idx, token.beginLine, token.beginColumn); }
}

void litNodeConstraint() : { String str; Token t; } {
(
t = <LITERAL>
{ constraintNodeKind(t.image, t.beginLine, t.beginColumn); }
Expand All @@ -267,17 +279,27 @@ void litNodeConstraint() : { String str; Token t; int idx; } {
(xsFacet())*
| (numericFacet())+
)
{ finishLiteralNodeConstraint(idx, token.beginLine, token.beginColumn); }
}

// Check precedence

void nonLitNodeConstraint() : { int idx; } {
void nonLitInlineNodeConstraint() : { int idx; } {
{ idx = startNonLiteralNodeConstraint(token.beginLine, token.beginColumn); }
nonLitNodeConstraint()
{ finishNonLiteralNodeConstraint(null, idx, token.beginLine, token.beginColumn); }
}

void nonLitOutlineNodeConstraint() : { int idx; List<SemAct> semActs; } {
{ idx = startNonLiteralNodeConstraint(token.beginLine, token.beginColumn); }
nonLitNodeConstraint()
semActs = semanticActions()
{ finishNonLiteralNodeConstraint(semActs, idx, token.beginLine, token.beginColumn); }
}

void nonLitNodeConstraint() : { } {
( nonLiteralKind() (stringFacet())*
| (stringFacet())+
)
{ finishNonLiteralNodeConstraint(idx, token.beginLine, token.beginColumn); }
}

void nonLiteralKind() : { Token t; }
Expand Down Expand Up @@ -336,14 +358,15 @@ String numericLength() : { Token t; }
void shapeDefinition() :
{ boolean closed = false; TripleExpression tripleExpr = null;
List<Node> extras = new ArrayList<Node>();
List<SemAct> semActs;
}
{
{ startShapeDefinition(); }
(extraPropertySet(extras) | <CLOSED> { closed = true; } )*
<LBRACE> (tripleExpr = tripleExpression())? <RBRACE>
(annotation())*
semanticActions()
{ finishShapeDefinition(tripleExpr, extras, closed); }
semActs = semanticActions()
{ finishShapeDefinition(tripleExpr, extras, closed, semActs); }
}

void inlineShapeDefinition() :
Expand All @@ -355,7 +378,7 @@ void inlineShapeDefinition() :
{ startShapeDefinition(); }
( extraPropertySet(extras) | <CLOSED> { closed = true; } )*
<LBRACE> (tripleExpr = tripleExpression())? <RBRACE>
{ finishShapeDefinition(tripleExpr, extras, closed); }
{ finishShapeDefinition(tripleExpr, extras, closed, null); }
}

void extraPropertySet(List<Node> extras) : { Node p; }
Expand Down Expand Up @@ -407,14 +430,14 @@ TripleExpression tripleExpression() : { int idx; }
{
{ idx = startTripleExpression(); }
tripleExpressionClause() (<VBAR> tripleExpressionClause())*
{ return finishTripleExpression(idx); }
{ return finishTripleExpression(idx, null); }
}

void tripleExpressionClause() : { int idx; } {
{ idx = startTripleExpressionClause(); }
// One of the rules below.
tripleExpressionClause_1()
{ finishTripleExpressionClause(idx); }
{ finishTripleExpressionClause(idx, null); }
}

// Iterative, but needs LOOKAHEAD(2)
Expand Down Expand Up @@ -445,26 +468,26 @@ void unaryTripleExpr() : { Node n = null; }
{ finishUnaryTripleExpr(); }
}

void bracketedTripleExpr(Node label): { TripleExpression tripleExpr = null; Cardinality cardinality = null; }
void bracketedTripleExpr(Node label): { TripleExpression tripleExpr = null; Cardinality cardinality = null; List<SemAct> semActs; }
{
{ startBracketedTripleExpr(); }
<LPAREN> tripleExpr = tripleExpression() <RPAREN>
(cardinality = cardinality())?
(annotation())*
semanticActions()
{ finishBracketedTripleExpr(label, tripleExpr, cardinality); }
semActs = semanticActions()
{ finishBracketedTripleExpr(label, tripleExpr, cardinality, semActs); }
}

void tripleConstraint(Node label) : { Node p; int idx; boolean reverse = false; Cardinality cardinality = null; }
void tripleConstraint(Node label) : { Node p; int idx; boolean reverse = false; Cardinality cardinality = null; List<SemAct> semActs; }
{
{ idx = startTripleConstraint(); }
( reverse = senseFlags() )?
p = predicate()
inlineShapeExpression()
(cardinality = cardinality())?
(annotation())*
semanticActions()
{ finishTripleConstraint(label, idx, p, reverse, cardinality); }
semActs = semanticActions()
{ finishTripleConstraint(label, idx, p, reverse, cardinality, semActs); }
}

Cardinality cardinality() : {}
Expand Down Expand Up @@ -648,13 +671,16 @@ void annotation() : {}
"//" predicate() (iri() | literal())
}

void semanticActions() : {}
List<SemAct> semanticActions() : {
List<SemAct> semActs = new ArrayList<SemAct>();
SemAct semAct;
}
{
// semanticAction : '%' iri (CODE | '%') ;
(codeDecl())*
(LOOKAHEAD(2)semAct = codeDecl() { semActs.add(semAct); })* { return semActs; }
}

void codeDecl() : {}
SemAct codeDecl() : { Token t; }
{
// Spec: - 2.1:
// codeDecl ::= '%' iri (CODE | '%'){
Expand All @@ -669,7 +695,7 @@ void codeDecl() : {}

// CODE_BLOCK this as a single token introduced with "%".

<CODE_BLOCK>
(t = <CODE_BLOCK>) { return crackSemanticAction(t.image, t.beginLine, t.beginColumn); }
}

Node literal() : { Node n ; }
Expand Down Expand Up @@ -940,9 +966,9 @@ TOKEN [IGNORE_CASE] :
//| <CODE : "{" (~[ "%","\\"] | "\\" ["%","\\"] )* "%" "}" >

| <CODE_BLOCK : <PERCENT_CHAR>
(" ")*
(" " | "\t" | "\n" | "\r" | "\f")*
(<IRIref>|<PNAME_LN>|<PNAME_NS>)
(" ")*
(" " | "\t" | "\n" | "\r" | "\f")*
( <LBRACE>
( ~[ "%","\\"] | ("\\" ["%","\\"]) | <UCHAR> )*
<PERCENT_CHAR><RBRACE>
Expand Down
25 changes: 25 additions & 0 deletions jena-shex/src/main/java/org/apache/jena/shex/Plugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.jena.shex;

public interface Plugin {

void register();

}
15 changes: 11 additions & 4 deletions jena-shex/src/main/java/org/apache/jena/shex/ShexSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import org.apache.jena.graph.Node;
import org.apache.jena.riot.system.PrefixMap;
import org.apache.jena.shex.expressions.SemAct;
import org.apache.jena.shex.expressions.TripleExpression;
import org.apache.jena.shex.sys.SysShex;

Expand All @@ -41,9 +42,10 @@ public class ShexSchema {
private final String baseURI;
private final PrefixMap prefixes;
private final List<String> imports;
private final List<SemAct> semActs;

public static ShexSchema shapes(String source, String baseURI, PrefixMap prefixes, ShexShape startShape,
List<ShexShape> shapes, List<String> imports,
List<ShexShape> shapes, List<String> imports, List<SemAct> semActs,
Map<Node, TripleExpression> tripleRefs) {
shapes = new ArrayList<>(shapes);
Map<Node, ShexShape> shapeMap = new LinkedHashMap<>();
Expand All @@ -56,19 +58,20 @@ public static ShexSchema shapes(String source, String baseURI, PrefixMap prefixe

tripleRefs = new LinkedHashMap<>(tripleRefs);

return new ShexSchema(source, baseURI, prefixes, startShape, shapes, shapeMap, imports, tripleRefs);
return new ShexSchema(source, baseURI, prefixes, startShape, shapes, shapeMap, imports, semActs, tripleRefs);
}

/*package*/ ShexSchema(String source, String baseURI, PrefixMap prefixes,
ShexShape startShape, List<ShexShape> shapes, Map<Node, ShexShape> shapeMap,
List<String> imports, Map<Node, TripleExpression> tripleRefMap) {
List<String> imports, List<SemAct> semActs, Map<Node, TripleExpression> tripleRefMap) {
this.sourceURI = source;
this.baseURI = baseURI;
this.prefixes = prefixes;
this.startShape = startShape;
this.shapes = shapes;
this.shapeMap = shapeMap;
this.imports = imports;
this.semActs = semActs;
this.tripleRefs = tripleRefMap;
}

Expand Down Expand Up @@ -147,7 +150,7 @@ public ShexSchema importsClosure() {
// mergedShapeMap.put(SysShex.startNode, startShape);
shapesWithImports = new ShexSchema(sourceURI, baseURI, prefixes,
startShape, mergedShapes, mergedShapeMap,
null/*imports*/, mergedTripleRefs);
null/*imports*/, semActs, mergedTripleRefs);
return shapesWithImports;
}
}
Expand Down Expand Up @@ -211,4 +214,8 @@ public boolean sameAs(Object obj) {
Objects.equals(shapeMap, other.shapeMap) &&
Objects.equals(startShape, other.startShape);
}

public List<SemAct> getSemActs() {
return semActs;
}
}
3 changes: 2 additions & 1 deletion jena-shex/src/main/java/org/apache/jena/shex/ShexShape.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public ShapeExpression getShapeExpression() {
public boolean satisfies(ValidationContext vCxt, Node data) {
vCxt.startValidate(this, data);
try {
return shExpression.satisfies(vCxt, data);
return shExpression.satisfies(vCxt, data) &&
shExpression.testShapeExprSemanticActions(vCxt, data);
} finally {
vCxt.finishValidate(this, data);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@

import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Node;
import org.apache.jena.shex.semact.SemanticActionPlugin;
import org.apache.jena.shex.sys.SysShex;

import java.util.Collection;

public interface ShexValidator {

/** Return the current system-wide {@code ShexValidator}. */
public static ShexValidator get() { return SysShex.get();}
public static ShexValidator getNew(Collection<SemanticActionPlugin> semanticActionPlugins) {
return SysShex.getNew(semanticActionPlugins);
}

/** Validate data using a collection of shapes and a shape map */
public ShexReport validate(Graph graph, ShexSchema shapes, ShapeMap shapeMap);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,4 @@ private static void arcsIn(Set<Triple> neigh, Graph graph, Node node) {
ExtendedIterator<Triple> x = G.find(graph, null, null, node);
x.forEach(neigh::add);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ else if ( partitions.isEmpty() )
break;
}
}
// This partition works.
if ( success )

// If this partition satisfies the nested expressions, test SemActs.
if ( success && eachOf.testSemanticActions(vCxt, matchables) )
return true;
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ static boolean matchesCardinalityTC(ValidationContext vCxt, Set<Triple> matchabl
vCxt.reportEntry(new ReportItem("Cardinality violation (max="+max+"): "+N, null));
return false;
}

boolean b = tripleConstraint.testSemanticActions(vCxt, matchables);
if ( ! b )
return false;

return true;
}
}
Loading

0 comments on commit ecffbee

Please sign in to comment.