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

grouped warnings and errors

parent 692b12f9
Loading
Loading
Loading
Loading
+51 −20
Original line number Diff line number Diff line
@@ -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 {
@@ -95,7 +99,8 @@ public class ReadOntology extends JobRunner {
			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())) {
				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);
@@ -157,20 +162,46 @@ 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 {
						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(String.format("Shape violation on node %s: %s%s", focusNode, resultMessage,
								gotString));
						logger.warn(message);
					}
				}
			}
@@ -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;
		}
+45 −118
Original line number Diff line number Diff line
@@ -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: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:message "The term should have at least one rdfs:label"
    ]
  ) .
[] a sh:NodeShape ;
  sh:targetClass owl:ObjectProperty ;
  sh:message "The owl:ObjectProperty should have at least one rdfs:label and one rdfs:comment" ;
  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."
				] 
	  	)
		] 
	) .
[] 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: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:message "The term should have at least one rdfs:comment"
    ]
  ) .