Skip to content

Commit 49170c2

Browse files
Merge pull request #185 from ashleycaselli/53-shaclinfersh-hangs-when-ttl-contains-some-specific-owlimports
53 shaclinfersh hangs when ttl contains some specific owlimports
2 parents 486da09 + c0e31bc commit 49170c2

File tree

9 files changed

+181
-166
lines changed

9 files changed

+181
-166
lines changed

.docker/Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ LABEL org.opencontainers.image.version=${VERSION}
1414

1515
# BUILD STAGE 1: install minimal Java environment + curl & zip for SHACL API
1616

17+
RUN apk add --no-cache binutils maven curl zip
18+
1719
# Create a custom Java runtime
1820
RUN $JAVA_HOME/bin/jlink \
1921
--add-modules java.base,java.compiler,java.desktop,java.management,java.naming,java.net.http,java.rmi,java.scripting,java.security.jgss,java.security.sasl,java.sql,java.xml.crypto,jdk.unsupported \
@@ -23,16 +25,14 @@ RUN $JAVA_HOME/bin/jlink \
2325
--compress=2 \
2426
--output /javaruntime
2527

26-
RUN apk add maven curl zip
27-
2828
# Compile with maven, extract binaries and copy into image
2929
COPY . /app
3030
RUN mvn versions:set -DnewVersion=${VERSION} && mvn package -Dmaven.test.skip=true
3131
RUN unzip target/shacl-${VERSION}-bin.zip -d /app/
3232

3333
# BUILD STAGE 2: keep only Java and SHACL
3434

35-
FROM alpine:3.20.3
35+
FROM alpine:3.21.2
3636

3737
ARG VERSION
3838

.docker/entrypoint.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ PARAMETER:
2323
input to be validated (only .ttl format supported)
2424
-shapesfile /data/myshapes.ttl [OPTIONAL]
2525
shapes for validation (only .ttl format supported)
26+
-maxiterations 1 [OPTIONAL] - default is 1
27+
iteratively applies the inference rules until the maximum number of iterations is reached (or no new triples are inferred)
28+
-validateShapes [OPTIONAL]
29+
in case you want to include the metashapes (from the tosh namespace in particular)
30+
-addBlankNodes [OPTIONAL]
31+
adds the blank nodes to the validation report
32+
-noImports [OPTIONAL]
33+
disables the import of external ontologies
2634
EOF
2735
exit 1
2836
fi

.github/workflows/docker-image.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ jobs:
3939
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
4040

4141
- name: Set up QEMU
42-
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0
42+
uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3.3.0
4343

4444
- name: Set up Docker Buildx
4545
id: buildx
46-
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
46+
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0
4747

4848
# inspired by https://github.com/reloc8/action-latest-release-version
4949
- name: Get release version
@@ -76,7 +76,7 @@ jobs:
7676

7777
- name: Build and push Docker image for x86 and arm64
7878
id: build
79-
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0
79+
uses: docker/build-push-action@b32b51a8eda65d6793cd0494a773d4f6bcef32dc # v6.11.0
8080
with:
8181
file: .docker/Dockerfile
8282
push: true
@@ -93,7 +93,7 @@ jobs:
9393
digest="${{ steps.build.outputs.digest }}"
9494
touch "/tmp/digests/${digest#sha256:}"
9595
- name: Upload digest
96-
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
96+
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
9797
with:
9898
name: digests-${{ matrix.package }}
9999
path: /tmp/digests/*
@@ -131,7 +131,7 @@ jobs:
131131
merge-multiple: true
132132

133133
- name: Set up Docker Buildx
134-
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
134+
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3.8.0
135135

136136
- name: Extract metadata (tags, labels) for Docker
137137
id: meta

.github/workflows/maven-test-pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
steps:
1616
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
1717
- name: Set up JDK
18-
uses: actions/setup-java@8df1039502a15bceb9433410b1a100fbe190c53b # v4.5.0
18+
uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
1919
with:
2020
distribution: ${{ matrix.distribution }}
2121
java-version: ${{ matrix.java }}

README.md

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ The binary distribution is:
5353

5454
`https://repo1.maven.org/maven2/org/topbraid/shacl/*VER*/shacl-*VER*-bin.zip`.
5555

56-
Two command line utilities are included: shaclvalidate (performs constraint validation) and shaclinfer (performs SHACL rule inferencing).
56+
Two command line utilities are included: `shaclvalidate` (performs constraint validation) and `shaclinfer` (performs SHACL rule inferencing).
5757

5858
To use them, set up your environment similar to https://jena.apache.org/documentation/tools/ (note that the SHACL download includes Jena).
5959

@@ -72,17 +72,13 @@ export SHACLROOT=/home/holger/shacl/shacl-1.4.3-bin/shacl-1.4.3/bin
7272
export PATH=$SHACLROOT:$PATH
7373
```
7474

75-
Both tools take the following parameters, for example:
75+
After setting up the environment, you can run the command line utilities (i.e. validation) using the following command:
7676

77-
`shaclvalidate.bat -datafile myfile.ttl -shapesfile myshapes.ttl`
77+
- Windows: `shaclvalidate.bat -datafile myfile.ttl -shapesfile myshapes.ttl`
7878

79-
where `-shapesfile` is optional and falls back to using the data graph as shapes graph.
80-
Add -validateShapes in case you want to include the metashapes (from the tosh namespace in particular).
79+
- Linux/Unix: `shaclvalidate.sh -datafile myfile.ttl -shapesfile myshapes.ttl`
8180

82-
For the shaclinfer tool, you can use the `-maxiterations` argument to apply SHACL rule inferencing multiple times; this will add inferred results back to the data graph to see if further triples can be inferred.
83-
The tool will iterate until either (a) the maximum number of iterations is reached, or (b) no new triples are inferred. The flag is optional and defaults to `1` (single iteration).
84-
85-
Currently only Turtle (.ttl) files are supported.
81+
Both tools (Windows, Linux) take the parameters described in the [Dockerfile Usage](#dockerfile-usage) section. **Currently, only Turtle (.ttl) files are supported.**
8682

8783
The tools print the validation report or the inferences graph to the output screen.
8884

@@ -113,15 +109,23 @@ Any other command after `ghcr.io/topquadrant/shacl:1.4.3` will print the followi
113109
Please use this docker image as follows:
114110
docker run -v /path/to/data:/data ghcr.io/topquadrant/shacl:1.4.3 [COMMAND] [PARAMETERS]
115111
COMMAND:
116-
validate
117-
to run validation
118-
infer
119-
to run rule inferencing
112+
validate
113+
to run validation
114+
infer
115+
to run rule inferencing
120116
PARAMETERS:
121-
-datafile /data/myfile.ttl [MANDATORY]
122-
input to be validated (only .ttl format supported)
123-
-shapesfile /data/myshapes.ttl [OPTIONAL]
124-
shapes for validation (only .ttl format supported)
117+
-datafile /data/myfile.ttl [MANDATORY]
118+
input to be validated (only .ttl format supported)
119+
-shapesfile /data/myshapes.ttl [OPTIONAL]
120+
shapes for validation (only .ttl format supported)
121+
-maxiterations 1 [OPTIONAL] - default is 1
122+
iteratively applies the inference rules until the maximum number of iterations is reached (or no new triples are inferred)
123+
-validateShapes [OPTIONAL]
124+
in case you want to include the metashapes (from the tosh namespace in particular)
125+
-addBlankNodes [OPTIONAL]
126+
adds the blank nodes to the validation report
127+
-noImports [OPTIONAL]
128+
disables the import of external ontologies
125129
```
126130

127131
If you'd like to build the image locally in an `x86` architecture, use:
@@ -134,4 +138,4 @@ If your architecture is `arm`, use:
134138

135139
```
136140
docker build -f .docker/Dockerfile -t ghcr.io/topquadrant/shacl:1.4.3 --build-arg VERSION=1.4.3 --build-arg ARCH_BASE=amazoncorretto:11-alpine3.18-jdk .
137-
```
141+
```

pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@
7070
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
7171
<ver.jena>5.2.0</ver.jena>
7272
<ver.junit>4.13.2</ver.junit>
73-
<ver.slf4j>1.7.36</ver.slf4j>
74-
<ver.log4j2>2.20.0</ver.log4j2>
73+
<ver.slf4j>2.0.16</ver.slf4j>
74+
<ver.log4j2>2.24.3</ver.log4j2>
7575
<java.version>17</java.version>
7676
</properties>
7777

@@ -99,7 +99,7 @@
9999
<!-- Require a logging implementation -->
100100
<dependency>
101101
<groupId>org.apache.logging.log4j</groupId>
102-
<artifactId>log4j-slf4j-impl</artifactId>
102+
<artifactId>log4j-slf4j2-impl</artifactId>
103103
<version>${ver.log4j2}</version>
104104
<optional>true</optional>
105105
</dependency>
@@ -210,7 +210,7 @@
210210
<plugin>
211211
<groupId>org.apache.maven.plugins</groupId>
212212
<artifactId>maven-javadoc-plugin</artifactId>
213-
<version>3.11.1</version>
213+
<version>3.11.2</version>
214214
<executions>
215215
<execution>
216216
<id>attach-javadocs</id>

src/main/java/org/topbraid/shacl/tools/AbstractTool.java

Lines changed: 73 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@
1616
*/
1717
package org.topbraid.shacl.tools;
1818

19-
import java.io.File;
20-
import java.io.FileInputStream;
21-
import java.io.IOException;
22-
import java.io.InputStream;
23-
2419
import org.apache.jena.ontology.OntDocumentManager;
2520
import org.apache.jena.ontology.OntModel;
2621
import org.apache.jena.ontology.OntModelSpec;
@@ -34,78 +29,78 @@
3429
import org.topbraid.shacl.vocabulary.SH;
3530
import org.topbraid.shacl.vocabulary.TOSH;
3631

32+
import java.io.*;
33+
3734
class AbstractTool {
3835

39-
private final static String DATA_FILE = "-datafile";
40-
41-
private final static String SHAPES_FILE = "-shapesfile";
42-
43-
private final static String MAX_ITERATIONS = "-maxiterations";
44-
45-
46-
private OntDocumentManager dm = new OntDocumentManager();
47-
48-
private OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM);
49-
50-
51-
AbstractTool() {
52-
53-
InputStream shaclTTL = SHACLSystemModel.class.getResourceAsStream("/rdf/shacl.ttl");
54-
Model shacl = JenaUtil.createMemoryModel();
55-
shacl.read(shaclTTL, SH.BASE_URI, FileUtils.langTurtle);
56-
shacl.add(SystemTriples.getVocabularyModel());
57-
dm.addModel(SH.BASE_URI, shacl);
58-
59-
InputStream dashTTL = SHACLSystemModel.class.getResourceAsStream("/rdf/dash.ttl");
60-
Model dash = JenaUtil.createMemoryModel();
61-
dash.read(dashTTL, SH.BASE_URI, FileUtils.langTurtle);
62-
dm.addModel(DASH.BASE_URI, dash);
63-
64-
InputStream toshTTL = SHACLSystemModel.class.getResourceAsStream("/rdf/tosh.ttl");
65-
Model tosh = JenaUtil.createMemoryModel();
66-
tosh.read(toshTTL, SH.BASE_URI, FileUtils.langTurtle);
67-
dm.addModel(TOSH.BASE_URI, tosh);
68-
69-
spec.setDocumentManager(dm);
70-
}
71-
72-
protected int getMaxIterations(String[] args) {
73-
for(int i = 0; i < args.length - 1; i++) {
74-
if(MAX_ITERATIONS.equals(args[i])) {
75-
return Integer.parseInt(args[i + 1]);
76-
}
77-
}
78-
return 1;
79-
}
80-
81-
protected Model getDataModel(String[] args) throws IOException {
82-
for(int i = 0; i < args.length - 1; i++) {
83-
if(DATA_FILE.equals(args[i])) {
84-
String dataFileName = args[i + 1];
85-
OntModel dataModel = ModelFactory.createOntologyModel(spec);
86-
File file = new File(dataFileName);
87-
String lang = FileUtils.langTurtle;
88-
dataModel.read(new FileInputStream(file), "urn:x:base", lang);
89-
return dataModel;
90-
}
91-
}
92-
System.err.println("Missing -datafile, e.g.: -datafile myfile.ttl");
93-
System.exit(0);
94-
return null;
95-
}
96-
97-
98-
protected Model getShapesModel(String[] args) throws IOException {
99-
for(int i = 0; i < args.length - 1; i++) {
100-
if(SHAPES_FILE.equals(args[i])) {
101-
String fileName = args[i + 1];
102-
OntModel model = ModelFactory.createOntologyModel(spec);
103-
File file = new File(fileName);
104-
String lang = FileUtils.langTurtle;
105-
model.read(new FileInputStream(file), "urn:x:base", lang);
106-
return model;
107-
}
108-
}
109-
return null;
110-
}
111-
}
36+
private final static String DATA_FILE = "-datafile";
37+
38+
private final static String SHAPES_FILE = "-shapesfile";
39+
40+
private final static String MAX_ITERATIONS = "-maxiterations";
41+
42+
protected final OntDocumentManager dm = new OntDocumentManager();
43+
44+
private OntModelSpec spec = new OntModelSpec(OntModelSpec.OWL_MEM);
45+
46+
47+
AbstractTool() {
48+
49+
InputStream shaclTTL = SHACLSystemModel.class.getResourceAsStream("/rdf/shacl.ttl");
50+
Model shacl = JenaUtil.createMemoryModel();
51+
shacl.read(shaclTTL, SH.BASE_URI, FileUtils.langTurtle);
52+
shacl.add(SystemTriples.getVocabularyModel());
53+
dm.addModel(SH.BASE_URI, shacl);
54+
55+
InputStream dashTTL = SHACLSystemModel.class.getResourceAsStream("/rdf/dash.ttl");
56+
Model dash = JenaUtil.createMemoryModel();
57+
dash.read(dashTTL, SH.BASE_URI, FileUtils.langTurtle);
58+
dm.addModel(DASH.BASE_URI, dash);
59+
60+
InputStream toshTTL = SHACLSystemModel.class.getResourceAsStream("/rdf/tosh.ttl");
61+
Model tosh = JenaUtil.createMemoryModel();
62+
tosh.read(toshTTL, SH.BASE_URI, FileUtils.langTurtle);
63+
dm.addModel(TOSH.BASE_URI, tosh);
64+
65+
spec.setDocumentManager(dm);
66+
}
67+
68+
protected int getMaxIterations(String[] args) {
69+
for (int i = 0; i < args.length - 1; i++) {
70+
if (MAX_ITERATIONS.equals(args[i])) {
71+
return Integer.parseInt(args[i + 1]);
72+
}
73+
}
74+
return 1;
75+
}
76+
77+
protected Model getDataModel(String[] args) throws IOException {
78+
for (int i = 0; i < args.length - 1; i++) {
79+
if (DATA_FILE.equals(args[i])) {
80+
return getModel(args, i);
81+
}
82+
}
83+
System.err.println("Missing -datafile, e.g.: -datafile myfile.ttl");
84+
System.exit(0);
85+
return null;
86+
}
87+
88+
protected Model getShapesModel(String[] args) throws IOException {
89+
for (int i = 0; i < args.length - 1; i++) {
90+
if (SHAPES_FILE.equals(args[i])) {
91+
return getModel(args, i);
92+
}
93+
}
94+
return null;
95+
}
96+
97+
private Model getModel(String[] args, int i) throws FileNotFoundException {
98+
String fileName = args[i + 1];
99+
OntModel dataModel = ModelFactory.createOntologyModel(spec);
100+
File file = new File(fileName);
101+
String lang = FileUtils.langTurtle;
102+
dataModel.read(new FileInputStream(file), "urn:x:base", lang);
103+
return dataModel;
104+
}
105+
106+
}

0 commit comments

Comments
 (0)