Commit e66bcb65 authored by Maxime Lefrançois's avatar Maxime Lefrançois
Browse files

grouped warnings and errors

parent 692b12f9
......@@ -7,10 +7,13 @@ import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.MalformedInputException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.jena.atlas.RuntimeIOException;
import org.apache.jena.datatypes.xsd.XSDDatatype;
......@@ -58,7 +61,8 @@ public class ReadOntology extends JobRunner {
+ " ?violation sh:focusNode ?focusNode .\n" + " ?violation sh:resultMessage ?resultMessage .\n"
+ " ?violation sh:resultSeverity ?severity .\n"
+ " OPTIONAL { ?violation sh:resultPath ?resultPath . }\n"
+ " OPTIONAL { ?violation sh:value ?value . } \n" + "}";
+ " OPTIONAL { ?violation sh:value ?value . } \n" + "}"
+ "ORDER BY ?severity ?resultMessage ?focusNode ";
static final Map<String, String> PREFIXES = new HashMap<String, String>();
static {
......@@ -94,8 +98,9 @@ public class ReadOntology extends JobRunner {
try (FileInputStream input = new FileInputStream(ontologyFile)) {
model.read(input, Constants.BASE, Lang.TTL.getLabel());
} catch (Exception ex) {
if(ex instanceof RuntimeIOException && ex.getCause() instanceof MalformedInputException) {
try (InputStreamReader input2 = new InputStreamReader(new FileInputStream(ontologyFile), Charset.defaultCharset())) {
if (ex instanceof RuntimeIOException && ex.getCause() instanceof MalformedInputException) {
try (InputStreamReader input2 = new InputStreamReader(new FileInputStream(ontologyFile),
Charset.defaultCharset())) {
model.read(input2, Constants.BASE, Lang.TTL.getLabel());
} catch (Exception ex2) {
logger.error("Exception while reading the ontology file", ex2);
......@@ -108,7 +113,7 @@ public class ReadOntology extends JobRunner {
}
checkPrefixes(model);
checkShapes(model, version);
// how does the TDB model work? documentation is not precise.
dataset.begin(ReadWrite.WRITE);
Model config = getNamedModel(dataset, Constants.CONFIG);
......@@ -157,28 +162,54 @@ public class ReadOntology extends JobRunner {
reportModel.setNsPrefixes(PREFIXES);
reportModel.setNsPrefix("sh", "http://www.w3.org/ns/shacl#");
try (QueryExecution exec = QueryExecutionFactory.create(SELECT_VIOLATION, reportModel);) {
Resource previousSeverity = null;
Literal previousResultMessage = null;
List<Resource> previousFocusNodes = new ArrayList<>();
List<RDFNode> previousvalues = new ArrayList<>();
for (ResultSet resultSet = exec.execSelect(); resultSet.hasNext();) {
QuerySolution sol = resultSet.next();
Resource severity = sol.getResource("severity");
Resource focusNode = sol.get("focusNode").asResource();
Literal resultMessage = sol.getLiteral("resultMessage");
Resource focusNode = sol.get("focusNode").asResource();
RDFNode value = sol.get("value");
String gotString = (value != null && value.isURIResource()) ? String.format(" Got: %s", value)
: "";
if (severity != null && severity.getURI().equals(SHACL_VIOLATION)) {
logger.error(String.format("Shape violation on node %s: %s%s", focusNode, resultMessage,
gotString));
if (severity != null && severity.equals(previousSeverity) && resultMessage != null
&& resultMessage.equals(previousResultMessage)) {
previousFocusNodes.add(focusNode);
previousvalues.add(value);
} else {
logger.warn(String.format("Shape violation on node %s: %s%s", focusNode, resultMessage,
gotString));
if (previousSeverity != null) {
String message = String.format("%s: %s", previousResultMessage,
String.join(" - ", previousFocusNodes.stream().map(Object::toString)
.collect(Collectors.toList()).toArray(new String[1])));
if (severity.getURI().equals(SHACL_VIOLATION)) {
logger.error(message);
} else {
logger.warn(message);
}
}
previousSeverity = severity;
previousResultMessage = resultMessage;
previousFocusNodes = new ArrayList<>();
previousvalues = new ArrayList<>();
}
}
if (!previousFocusNodes.isEmpty()) {
String message = String.format("%s: %s", previousResultMessage,
String.join(" - ", previousFocusNodes.stream().map(Object::toString)
.collect(Collectors.toList()).toArray(new String[1])));
if (previousSeverity != null && previousSeverity.getURI().equals(SHACL_VIOLATION)) {
logger.error(message);
} else {
logger.warn(message);
}
}
}
}
int onto = 0;
for(ResIterator it = model.listSubjectsWithProperty(RDF.type, OWL2.Ontology) ; it.hasNext() ; ) {
for (ResIterator it = model.listSubjectsWithProperty(RDF.type, OWL2.Ontology); it.hasNext();) {
Resource ontology = it.next();
if(onto++>1) {
if (onto++ > 1) {
logger.error("There shall be only one owl:Ontology");
}
// if(version instanceof ReleaseVersion) {
......@@ -244,7 +275,7 @@ public class ReadOntology extends JobRunner {
config.add(t, EX.isUsedBy, version.getResource());
}
}
private void updateOntologyMetadata(Version version, Model model) {
Resource ontologySeries = version.getRepository().getResource();
model.add(ontologySeries, RDF.type, OWL2.Ontology);
......@@ -281,6 +312,7 @@ public class ReadOntology extends JobRunner {
model.add(DCTerms.license, RDF.type, OWL.AnnotationProperty);
model.add(SCHEMA.Person, RDF.type, OWL.Class);
model.add(SCHEMA.Organization, RDF.type, OWL.Class);
model.add(SCHEMA.affiliation, RDF.type, OWL.ObjectProperty);
model.add(SCHEMA.familyName, RDF.type, OWL.DatatypeProperty);
model.add(SCHEMA.givenName, RDF.type, OWL.DatatypeProperty);
model.add(SCHEMA.name, RDF.type, OWL.DatatypeProperty);
......@@ -304,14 +336,14 @@ public class ReadOntology extends JobRunner {
model.removeAll(ontologySeries, VANN.preferredNamespacePrefix, null);
model.removeAll(ontologySeries, VANN.preferredNamespaceUri, null);
model.add(ontologySeries, VANN.preferredNamespacePrefix, version.getRepository().getPrefix());
model.add(ontologySeries, VANN.preferredNamespaceUri, version.getRepository().getNamespace(), XSDDatatype.XSDanyURI);
model.add(ontologySeries, VANN.preferredNamespaceUri, version.getRepository().getNamespace(),
XSDDatatype.XSDanyURI);
model.removeAll(ontologySeries, DCTerms.issued, null);
model.add(ontologySeries, DCTerms.issued, SIMPLE_DATE_FORMAT.format(version.getIssued()), XSDDatatype.XSDdate);
}
private void computeTerms(Version version, Model model, Set<Resource> definedTerms,
Set<Resource> usedTerms) {
private void computeTerms(Version version, Model model, Set<Resource> definedTerms, Set<Resource> usedTerms) {
model.listStatements().forEachRemaining(stmt -> {
Resource s = stmt.getSubject();
Resource p = stmt.getPredicate();
......@@ -322,8 +354,7 @@ public class ReadOntology extends JobRunner {
});
}
private void computeTerms(Version version, Resource t, Set<Resource> definedTerms,
Set<Resource> usedTerms) {
private void computeTerms(Version version, Resource t, Set<Resource> definedTerms, Set<Resource> usedTerms) {
if (t == null || !t.isURIResource() || !t.getURI().startsWith(Constants.BASE) || t.getURI().endsWith("/")) {
return;
}
......
......@@ -22,19 +22,19 @@ sarefsh:OntologyShape
sh:path owl:versionInfo ;
sh:maxCount 0 ;
sh:severity sh:Warning ;
sh:message "The annotation owl:versionInfo shall not be set in the source file, as it will be computed automatically."
sh:message "The annotation owl:versionInfo should not be set in the source file, as it will be computed automatically"
] ;
sh:property [
sh:path owl:versionIRI ;
sh:maxCount 0 ;
sh:severity sh:Warning ;
sh:message "The annotation owl:versionIRI shall not be set in the source file, as it will be computed automatically."
sh:message "The annotation owl:versionIRI should not be set in the source file, as it will be computed automatically"
] ;
sh:property [
sh:path owl:priorVersion ;
sh:maxCount 0 ;
sh:severity sh:Warning ;
sh:message "The annotation owl:priorVersion shall not be set in the source file, as it will be computed automatically."
sh:message "The annotation owl:priorVersion should not be set in the source file, as it will be computed automatically"
] ;
sh:property [
sh:path owl:imports ;
......@@ -49,7 +49,7 @@ sarefsh:OntologyShape
sh:minCount 1 ;
sh:maxCount 1 ;
sh:severity sh:Violation ;
sh:message "The ontology should have exactly one <http://purl.org/dc/terms/title>."
sh:message "The ontology shall have exactly one <http://purl.org/dc/terms/title>"
] ;
sh:property [
sh:path dcterms:abstract ;
......@@ -57,7 +57,7 @@ sarefsh:OntologyShape
sh:minCount 1 ;
sh:maxCount 1 ;
sh:severity sh:Warning ;
sh:message "The ontology should have exactly one <http://purl.org/dc/terms/abstract>."
sh:message "The ontology should have exactly one <http://purl.org/dc/terms/abstract>"
] ;
sh:property [
sh:path dcterms:description ;
......@@ -65,7 +65,7 @@ sarefsh:OntologyShape
sh:minCount 1 ;
sh:maxCount 1 ;
sh:severity sh:Warning ;
sh:message "The ontology should have exactly one <http://purl.org/dc/terms/description>."
sh:message "The ontology should have exactly one <http://purl.org/dc/terms/description>"
] ;
sh:property [
sh:path rdfs:comment ;
......@@ -83,7 +83,7 @@ sarefsh:OntologyShape
sh:datatype xsd:date ;
sh:maxCount 0 ;
sh:severity sh:Warning ;
sh:message "The annotation <http://purl.org/dc/terms/modified> shall not be set in the source file, as it will be computed automatically."
sh:message "The annotation <http://purl.org/dc/terms/modified> will be computed automatically"
] ;
sh:property [
sh:path dcterms:source ;
......@@ -96,51 +96,51 @@ sarefsh:OntologyShape
sh:minCount 1 ;
sh:pattern "https://forge.etsi.org/etsi-software-license" ;
sh:severity sh:Violation ;
sh:message "There shall be at least one annotation <http://purl.org/dc/terms/license> <https://forge.etsi.org/etsi-software-license>."
sh:message "There shall be at least one annotation <http://purl.org/dc/terms/license> <https://forge.etsi.org/etsi-software-license>"
] ;
sh:property [
sh:path dcterms:creator ;
sh:nodeKind sh:BlankNodeOrIRI ;
sh:minCount 0 ;
sh:severity sh:Warning ;
sh:message "The <http://purl.org/dc/terms/creator> shall be blank nodes or IRIs."
sh:message "The <http://purl.org/dc/terms/creator> should be blank nodes or IRIs"
] ;
sh:property [
sh:path dcterms:creator ;
sh:severity sh:Warning ;
sh:node sarefsh:PersonShape ;
sh:message "Every creator shall be a <http://schema.org/Person> with <http://schema.org/givenName>, <http://schema.org/familyName>, and <http://schema.org/affiliation>."
sh:message "Every creator should be a <http://schema.org/Person> with <http://schema.org/givenName>, <http://schema.org/familyName>, and <http://schema.org/affiliation>"
] ;
sh:property [
sh:path dcterms:contributor ;
sh:nodeKind sh:BlankNodeOrIRI ;
sh:minCount 0 ;
sh:severity sh:Warning ;
sh:message "The <http://purl.org/dc/terms/contributor> shall be blank nodes or IRIs."
sh:message "The <http://purl.org/dc/terms/contributor> should be blank nodes or IRIs"
] ;
sh:property [
sh:path dcterms:contributor ;
sh:severity sh:Warning ;
sh:node sarefsh:PersonShape ;
sh:message "Every contributor shall be a <http://schema.org/Person> with <http://schema.org/givenName>, <http://schema.org/familyName>, and <http://schema.org/affiliation>."
sh:message "Every contributor should be a <http://schema.org/Person> with <http://schema.org/givenName>, <http://schema.org/familyName>, and <http://schema.org/affiliation>"
] ;
sh:property [
sh:path dcterms:publisher ;
sh:maxCount 0 ;
sh:severity sh:Warning ;
sh:message "The annotation <http://purl.org/dc/terms/publisher> shall not be set in the source file, as it will be computed automatically."
sh:message "The annotation <http://purl.org/dc/terms/publisher> will be computed automatically"
] ;
sh:property [
sh:path vann:preferredNamespacePrefix ;
sh:maxCount 0 ;
sh:severity sh:Warning ;
sh:message "The annotation <http://purl.org/vocab/vann/preferredNamespacePrefix> shall not be set in the source file, as it will be computed automatically."
sh:message "The annotation <http://purl.org/vocab/vann/preferredNamespacePrefix> will be computed automatically"
] ;
sh:property [
sh:path vann:preferredNamespaceUri ;
sh:maxCount 0 ;
sh:severity sh:Warning ;
sh:message "The annotation <http://purl.org/vocab/vann/preferredNamespaceUri> shall not be set in the source file, as it will be computed automatically."
sh:message "The annotation <http://purl.org/vocab/vann/preferredNamespaceUri> will be computed automatically"
] .
sarefsh:PersonShape
......@@ -151,19 +151,19 @@ sarefsh:PersonShape
sh:path rdf:type ;
sh:hasValue schema:Person ;
sh:severity sh:Warning ;
sh:message "Each contributor shall be a <http://schema.org/Person>."
sh:message "Every contributor should be a <http://schema.org/Person>"
] ;
sh:property [
sh:path schema:givenName ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "Each contributor shall have at least one <http://schema.org/givenName>."
sh:message "Every contributor should have at least one <http://schema.org/givenName>"
] ;
sh:property [
sh:path schema:familyName ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "Each contributor shall have at least one <http://schema.org/lastName>."
sh:message "Every contributor should have at least one <http://schema.org/lastName>"
] ;
sh:property [
sh:path schema:affiliation ;
......@@ -171,7 +171,7 @@ sarefsh:PersonShape
sh:nodeKind sh:BlankNodeOrIRI ;
sh:node sarefsh:AffiliationShape ;
sh:severity sh:Warning ;
sh:message "Each contributor shall have at least one <http://schema.org/affiliation>, that shall be a blank node or a IRI of type <http://schema.org/Organization> with at least one <http://schema.org/name>."
sh:message "Every contributor should have at least one <http://schema.org/affiliation>, that should be a blank node or a IRI of type <http://schema.org/Organization> with at least one <http://schema.org/name>"
] .
sarefsh:AffiliationShape
......@@ -182,112 +182,39 @@ sarefsh:AffiliationShape
sh:path rdf:type ;
sh:hasValue schema:Organization ;
sh:severity sh:Warning ;
sh:message "The affiliation of each contributor shall be a <http://schema.org/Organization>."
sh:message "The affiliation of each contributor should be a <http://schema.org/Organization>"
] ;
sh:property [
sh:path schema:name ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The affiliation of each contributor shall have at least one <http://schema.org/name>."
sh:message "The affiliation of each contributor should have at least one <http://schema.org/name>"
] .
[] a sh:NodeShape ;
sh:targetClass owl:Class ;
sh:message "The owl:Class should have at least one rdfs:label and one rdfs:comment" ;
sh:severity sh:Warning ;
sh:or (
[ sh:nodeKind sh:BlankNode ]
[
sh:and (
[
sh:path rdfs:label ;
sh:nodeKind sh:Literal ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The term should have at least one rdfs:label."
]
[
sh:path rdfs:comment ;
sh:nodeKind sh:Literal ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The term should have at least one rdfs:comment."
]
)
]
) .
[] a sh:NodeShape ;
sh:targetClass owl:ObjectProperty ;
sh:message "The owl:ObjectProperty should have at least one rdfs:label and one rdfs:comment" ;
sh:severity sh:Warning ;
sh:targetClass owl:Class, owl:ObjectProperty, owl:DatatypeProperty , owl:NamedIndividual;
sh:message "The following terms do not have at least one rdfs:label" ;
sh:severity sh:Warning ;
sh:or (
[ sh:nodeKind sh:BlankNode ]
[
sh:and (
[
sh:path rdfs:label ;
sh:nodeKind sh:Literal ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The term should have at least one rdfs:label."
]
[
sh:path rdfs:comment ;
sh:nodeKind sh:Literal ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The term should have at least one rdfs:comment."
]
)
]
) .
[ sh:nodeKind sh:BlankNode ]
[
sh:path rdfs:label ;
sh:nodeKind sh:Literal ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The term should have at least one rdfs:label"
]
) .
[] a sh:NodeShape ;
sh:targetClass owl:DatatypeProperty ;
sh:message "The owl:DatatypeProperty should have at least one rdfs:label and one rdfs:comment" ;
sh:severity sh:Warning ;
sh:or (
[ sh:nodeKind sh:BlankNode ]
[
sh:and (
[
sh:path rdfs:label ;
sh:nodeKind sh:Literal ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The term should have at least one rdfs:label."
]
[
sh:path rdfs:comment ;
sh:nodeKind sh:Literal ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The term should have at least one rdfs:comment."
]
)
]
) .
[] a sh:NodeShape ;
sh:targetClass owl:NamedIndividual ;
sh:message "The owl:NamedIndividual should have at least one rdfs:label and one rdfs:comment" ;
sh:severity sh:Warning ;
sh:targetClass owl:Class, owl:ObjectProperty, owl:DatatypeProperty , owl:NamedIndividual;
sh:message "The following terms do not have at least one rdfs:comment" ;
sh:severity sh:Warning ;
sh:or (
[ sh:nodeKind sh:BlankNode ]
[
sh:and (
[
sh:path rdfs:label ;
sh:nodeKind sh:Literal ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The term should have at least one rdfs:label."
]
[
sh:path rdfs:comment ;
sh:nodeKind sh:Literal ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The term should have at least one rdfs:comment."
]
)
]
) .
\ No newline at end of file
[ sh:nodeKind sh:BlankNode ]
[
sh:path rdfs:comment ;
sh:nodeKind sh:Literal ;
sh:minCount 1 ;
sh:severity sh:Warning ;
sh:message "The term should have at least one rdfs:comment"
]
) .
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment