Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • saref/saref-pipeline
1 result
Show changes
Commits on Source (2)
......@@ -27,8 +27,8 @@ package fr.mines_stetienne.ci.saref.checkers;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.util.stream.Collectors;
......@@ -74,8 +74,10 @@ public class Clause_9_4_6_Checker extends AbstractClauseChecker {
// First get the available directories. If none, not a problem.
File dir2 = new File(repository.getDirectory(), "patterns");
String[] directoryList = new String[]{};
List<String> shaclFileList = new ArrayList();
// process every shapes.ttl file in the sub-directories of the patterns directory.
try {
String[] directoryList = new String[]{};
String directories = Files.walk(dir2.toPath()).filter(p -> {
try {
return p.toFile().isDirectory() && !Files.isSameFile(dir2.toPath(), p);
......@@ -87,24 +89,22 @@ public class Clause_9_4_6_Checker extends AbstractClauseChecker {
return; // no SHACL directories found.
}
directoryList = directories.split(",");
for(int i = 0; i < directoryList.length; i++) {
shaclFileList.add(directoryList[i] + "/shapes.ttl");
}
} catch (IOException e) {
logError(getMessage(Clause_9_4_6_Checker.MESSAGE.ioexception), e);
}
ShaclValidationManager.PingValidationServer();
Map<String, HttpResponse<String>> responseMap = new HashMap<String, HttpResponse<String>>();
// process every shapes.ttl file in the sub-directories of the patterns directory.
for(int i = 0; i < directoryList.length; i++) {
String shaclFileName = directoryList[i] + "/shapes.ttl"; // "file://" +
try {
HttpResponse<String> response = new ShaclValidationManager(ontologyToValidate).validateOntologyWithShacl(shaclFileName);
System.out.println(response); //<<<
responseMap.put(shaclFileName, response); //<<< parse map for errors
} catch (IOException | InterruptedException e) {
logError(getMessage(Clause_9_4_6_Checker.MESSAGE.ioexception, shaclFileName));
}
//Map<String, HttpResponse<String>> responseMap = new HashMap<String, HttpResponse<String>>();
try {
ShaclValidationManager shaclValidationManager = new ShaclValidationManager(ontologyToValidate);
HttpResponse<String> response = shaclValidationManager.ValidateOntologyWithShacl(shaclFileList);
//responseMap.put(shaclFileName, response); // parse map for errors
} catch (IOException | InterruptedException e) {
logError(getMessage(Clause_9_4_6_Checker.MESSAGE.ioexception, ontologyToValidate));
}
//System.out.println(responseMap); //<<<
}
}
\ No newline at end of file
......@@ -32,30 +32,34 @@ import java.net.URL;
import java.net.URLEncoder;
import java.net.http.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Base64;
import java.util.List;
import java.util.ArrayList;
//import java.util.HashMap;
import org.apache.commons.lang3.StringEscapeUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import fr.mines_stetienne.ci.saref.SAREFPipelineException;
/* docker run -d --name SAREFvalidator -p 8080:8080 isaitb/shacl-validator # runs the generic validator.
/* docker run -d --name SAREFvalidator -p 8080:8080 isaitb/shacl-validator # runs the generic validator with Dockerfile
Docs for RDF validator: https://www.itb.ec.europa.eu/docs/guides/latest/validatingRDF/index.html
Base docker image: https://hub.docker.com/r/isaitb/shacl-validator (generic validator)
Use Swagger UI for testing: http://localhost:8080/shacl/swagger-ui/index.html#/{domain}/api/validate
BASE64 Encoder/Decoder: https://www.base64encode.org/
* */
public class ShaclValidationManager {
private static String VALIDATOR_URL = "http://localhost:8080/shacl/";
private final String TEXT_TURTLE = "text/turtle";
private final String JSON_FORMAT = "application/json"; // application/x-www-form-urlencoded
private final String STRING_FORMAT = "STRING";
private String ontologyToValidate; // file:///home/davidgnabasik/dev/real_saref4auto/ontology/saref4auto.ttl or URL
private List<String> shaclFileList;
private List<RuleSet> ruleSetList;
private HttpClient client;
private ObjectMapper objectMapper;
//private String shaclRequestBody =
// "{ \"contentToValidate\": \"ONTOLOGY_AS_BASE64_STRING\", \"embeddingMethod\": \"BASE64\", \"contentSyntax\": \"text/turtle\", \"reportSyntax\": \"application/json\", \"locale\": \"en\", \"rdfReportSyntax\": \"application/json\", \"externalRules\": [ { \"ruleSet\": \"SHACL_AS_BASE64_STRING\", \"embeddingMethod\": \"BASE64\", \"ruleSyntax\": \"text/turtle\" } ] }";
private ValidationRequest validationRequest;
private static String encodeBody(Object obj) {
return URLEncoder.encode(obj.toString(), StandardCharsets.UTF_8);
......@@ -65,12 +69,78 @@ public class ShaclValidationManager {
http_exception, ioexception
}
class RuleSet {
private String ruleSet; // JSON-encoded_SHACL_shape
public String getRuleSet() {
return ruleSet;
}
public void setRuleSet(String ruleSet) {
this.ruleSet = ruleSet;
}
// constants for now...
public String getEmbeddingMethod() { return STRING_FORMAT; }
public String getRuleSyntax() { return TEXT_TURTLE; }
}
class ValidationRequest {
private String contentToValidate; // JSON-encoded ontology
private List<RuleSet> externalRules;
private Map<String, Object> properties; // needed?
public String getContentToValidate() {
return contentToValidate;
}
public void setContentToValidate(String contentToValidate) {
this.contentToValidate = contentToValidate;
}
public Map<String, Object> getProperties() {
return properties;
}
public void setProperties(Map<String, Object> properties) {
this.properties = properties;
}
// constants for now...
public String getEmbeddingMethod() {
return STRING_FORMAT;
}
public String getContentSyntax() {
return TEXT_TURTLE;
}
public String getReportSyntax() {
return JSON_FORMAT;
}
public String getRdfReportSyntax() {
return JSON_FORMAT;
}
public String getLocale() {
return "en";
}
public List<RuleSet> getExternalRules() {
return externalRules;
}
public void setExternalRules(List<RuleSet> externalRules) {
this.externalRules = externalRules;
}
}
/**
* Open a REST interface to the SHACL validator.
*/
public ShaclValidationManager(String ontologyToValidate) throws IOException {
client = HttpClient.newHttpClient();
objectMapper = new ObjectMapper();
this.client = HttpClient.newHttpClient();
this.objectMapper = new ObjectMapper();
this.ontologyToValidate = ontologyToValidate;
String url = System.getenv("VALIDATOR_URL");
if (url != null) VALIDATOR_URL = url;
......@@ -94,19 +164,49 @@ public class ShaclValidationManager {
}
/**
* Preferred validation format is BASE64. Read file; return single BASE64-encoded string.
* Read shacl files. Assign this.shaclFileList, this.ruleSetList.
* Preferred validation format is JSON-escaped text. Requires \r\n as line breaks!!!
*/
private void createRuleSetList(List<String> shaclFileList) {
this.shaclFileList = new ArrayList();
this.ruleSetList = new ArrayList();
for (int i = 0; i < shaclFileList.size(); i++) {
String readingFile = shaclFileList.get(i);
try {
String fileStr = new String(Files.readAllBytes(Paths.get(readingFile)));
RuleSet ruleSet = new RuleSet();
ruleSet.setRuleSet(fileStr); //.replaceAll("[\n]","\r\n"));
this.shaclFileList.add(readingFile);
this.ruleSetList.add(ruleSet);
} catch (IOException ex) {
System.out.println("ShaclValidationManager unable to read SHACL file: " + readingFile);
}
}
}
/**
* Assign ValidationRequest object.
* Preferred validation format is JSON-escaped text. Requires \r\n as line breaks!!!
* @throws SAREFPipelineException
*/
public static String FormatAsBase64(String ontologyFile) throws SAREFPipelineException {
private void createValidationRequest(List<String> shaclFileList) throws SAREFPipelineException {
createRuleSetList(shaclFileList);
if (this.ruleSetList.size() < 1) {
throw new SAREFPipelineException("ShaclValidationManager", "No SHACL files to process!");
}
// process ontology file
try {
String value = Files.readString(Path.of(ontologyFile)); // 2Gb file size limit.
return Base64.getUrlEncoder().encodeToString(value.getBytes());
String fileStr = new String(Files.readAllBytes(Paths.get(this.ontologyToValidate)));
this.validationRequest = new ValidationRequest();
this.validationRequest.setContentToValidate(fileStr); // .replaceAll("[\n]","\r\n"));
this.validationRequest.setExternalRules(this.ruleSetList);
} catch (IOException ex) {
throw new SAREFPipelineException("FormatAsBase64", "Unable to format file as base64: " + ontologyFile);
throw new SAREFPipelineException("ShaclValidationManager", "Unable to read ontology file: " + this.ontologyToValidate);
}
}
public static HttpRequest.BodyPublisher ofForm(Map<String, Object> data) {
private HttpRequest.BodyPublisher ofForm(Map<String, Object> data) {
StringBuilder body = new StringBuilder();
for (Object dataKey : data.keySet()) {
if (body.length() > 0) {
......@@ -121,46 +221,30 @@ public class ShaclValidationManager {
/**
* POST JSON response format:
{
"date": "2024-04-05T10:18:24.197+0000",
"result": "SUCCESS",
"overview": {
"profileID": "Clause_9_4_3_1"
},
"counters": {
"nrOfAssertions": 0,
"nrOfErrors": 0,
"nrOfWarnings": 0
},
"context": {},
"reports": {},
"name": "SHACL Validation"
}
* Generic validator option: 1. Replace {contentToValidate} value with the ontology to validate encoded in BASE64. (This can aos be done with URLs.)
* 2. Configure the user-provided SHACL shape as a RuleSet element of the externalRules array. The content of each RuleSet is as follows:
* [ "ruleSet": "BASE64-encoded_SHACL_shape", "embeddingMethod":"BASE64", "ruleSyntax": "text/turtle" ] We run one SHACL shape at a time.
* POST request to Validate a single RDF instance.
LIST OF: @prefix : <https://saref.etsi.org/saref4auto/> .
[ rdf:type sh:ValidationReport ;
sh:conforms true
] .
* Generic validator option: 1. Replace {contentToValidate} value with the ontology to validate encoded in JSON. This can also be done with URLs.
* 2. Configure the user-provided SHACL shape as a RuleSet element of the externalRules array.
* [ "ruleSet": "JSON-encoded_SHACL_shape", "embeddingMethod":"STRING", "ruleSyntax": TEXT_TURTLE ]
* POST request to Validate a single RDF ontology.
* @throws SAREFPipelineException
* @throws IOException
* @throws InterruptedException
*/
public HttpResponse<String> validateOntologyWithShacl(String shaclFile) throws SAREFPipelineException, InterruptedException {
public HttpResponse<String> ValidateOntologyWithShacl(List<String> shaclFileList) throws SAREFPipelineException, InterruptedException {
try {
String ontologyBase64String = FormatAsBase64(this.ontologyToValidate);
String shaclBase64String = FormatAsBase64(shaclFile);
// populate shaclRequestBody json struct to map (no TypeReference)
String shaclRequestBody = "{ \"contentToValidate\": \"" + ontologyBase64String +
"\", \"embeddingMethod\": \"BASE64\", \"contentSyntax\": \"text/turtle\", \"reportSyntax\": \"application/json\", \"locale\": \"en\", \"rdfReportSyntax\": \"application/json\", \"externalRules\": [ { \"ruleSet\": \"" +
shaclBase64String + "\", \"embeddingMethod\": \"BASE64\", \"ruleSyntax\": \"text/turtle\" } ] }";
byte[] mapData = shaclRequestBody.getBytes();
Map<String,Object> myMap = objectMapper.readValue(mapData, HashMap.class);
// now update JSON data
//myMap.put("contentToValidate", ontologyBase64String);
//myMap.put("ruleSet", shaclBase64String);
createValidationRequest(shaclFileList);
String jsonStr = this.objectMapper.writeValueAsString(this.validationRequest);
String escapedJson = StringEscapeUtils.escapeJson(jsonStr);
System.out.println(escapedJson);//<<<
HttpRequest request = HttpRequest.newBuilder()
.header("Content-Type", "text/turtle") // application/x-www-form-urlencoded
.uri(URI.create(VALIDATOR_URL + "any/upload"))
.POST(ofForm(myMap))
.header("Content-Type", JSON_FORMAT)
.uri(URI.create(VALIDATOR_URL + "any/upload")) // any/api/validate
.POST(HttpRequest.BodyPublishers.ofString(jsonStr)) // escapedJson
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
......@@ -168,7 +252,7 @@ public class ShaclValidationManager {
System.out.println("\n Body: " + response.body());
return response;
} catch (IOException ex) {
throw new SAREFPipelineException("validateOntologyWithShacl", "Unable to process SHACL file: " + shaclFile);
throw new SAREFPipelineException("ValidateOntologyWithShacl", "Unable to validate ontology: " + this.ontologyToValidate);
}
}
......
server_unavailable=The validation server is unavailable at `%s`
ioexception=Error while accessing the local file system
missing=The shacl directory should contain at least one file. This file shall conform to the pattern specification as defined in clause 9.4.6 in TS 103 673.
one=If a shacl directory exists, it should contain at least one shapes.ttl file.