/* * Copyright 2020 ETSI * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package fr.mines_stetienne.ci.saref.checkers; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.Set; import java.util.stream.Collectors; import org.apache.jena.rdf.model.Model; import org.semanticweb.owl.explanation.api.Explanation; import org.semanticweb.owl.explanation.api.ExplanationGenerator; import org.semanticweb.owlapi.model.OWLAxiom; import org.semanticweb.owlapi.model.OWLOntology; import org.semanticweb.owlapi.profiles.OWL2DLProfile; import org.semanticweb.owlapi.profiles.OWLProfileReport; import org.semanticweb.owlapi.profiles.violations.UseOfDefinedDatatypeInDatatypeRestriction; import org.semanticweb.owlapi.profiles.violations.UseOfDefinedDatatypeInLiteral; import org.semanticweb.owlapi.profiles.violations.UseOfUndeclaredDatatype; import org.semanticweb.owlapi.profiles.violations.UseOfUnknownDatatype; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import fr.mines_stetienne.ci.saref.SAREF; import fr.mines_stetienne.ci.saref.SAREFPipelineException; import fr.mines_stetienne.ci.saref.managers.OntologyManager; import fr.mines_stetienne.ci.saref.managers.RepositoryManager; import fr.mines_stetienne.ci.saref.managers.ThemisManager; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; /** * Checks TS 103 673 Clause 9.4.5: OWL Profile, Consistency, and Satisfiability * of Classes * */ public class Clause_9_4_5_Checker extends AbstractClauseChecker { private static enum MESSAGE { profile, consistent, satisfiable, oops, oopsError; } /** */ public Clause_9_4_5_Checker(RepositoryManager repositoryManager) { super(repositoryManager, Clause_9_4_5_Checker.class); } @Override public void checkClause() throws SAREFPipelineException { final OWLOntology ontology = pipeline.getOntologyManager().loadOntology(version, errorLogger); if (ontology == null) { return; } final OWLProfileReport report = new OWL2DLProfile().checkOntology(ontology); report.getViolations().removeIf(v -> { if (v instanceof UseOfDefinedDatatypeInDatatypeRestriction || v instanceof UseOfDefinedDatatypeInLiteral || v instanceof UseOfUndeclaredDatatype || v instanceof UseOfUnknownDatatype) { return true; } return false; }); if (!report.getViolations().isEmpty()) { String violations = report.getViolations().stream().map(Object::toString) .collect(Collectors.joining("\n- ", "\n\n- ", "\n\n")); logError(getMessage(MESSAGE.profile, violations)); } OntologyManager ontologyManager = pipeline.getOntologyManager(); Set> incExplanation = ontologyManager.getInconsistenceExplanations(ontology, errorLogger); if (incExplanation != null && !incExplanation.isEmpty()) { String explanation = incExplanation.stream().map(e -> e.getAxioms().toString()) .collect(Collectors.joining("\n- ", "\n\n- ", "\n\n")); logError(getMessage(MESSAGE.consistent, explanation)); } else { ExplanationGenerator generator = ontologyManager.getExplanationGenerator(ontology); ontology.classesInSignature().forEach(c -> { if (c.isOWLNothing()) { return; } Set> incExplanation2 = ontologyManager.getIncoherenceExplanations(generator, c); if (!incExplanation2.isEmpty()) { String explanation = incExplanation2.stream().map(e -> e.getAxioms().toString()) .collect(Collectors.joining("\n- ", "\n\n- ", "\n\n")); logError(getMessage(MESSAGE.satisfiable, c, explanation)); } }); } try { checkOops(); } catch (Exception ex) { logWarning(getMessage(MESSAGE.oopsError), ex); } } public void checkOops() throws Exception { if (SAREF.IGNORE_OOPS) { return; } ByteArrayOutputStream out = new ByteArrayOutputStream(); String onto = ""; Model model = version.getModel(); model.write(out, "RDF/XML"); // write in string and then replace onto = out.toString().replaceAll("]]", "] ]"); String xmlRequest = "" + "" + "" + "" + "" + "RDF/XML" + ""; Object[] arrayData = new Object[0]; try { OkHttpClient httpClient = new OkHttpClient().newBuilder().build(); MediaType mediaType = MediaType.parse("application/xml"); RequestBody body = RequestBody.create(xmlRequest, mediaType); Request request = new Request.Builder().url("http://oops.linkeddata.es/rest").method("POST", body) .addHeader("Content-Type", "application/xml").build(); try (Response response = httpClient.newCall(request).execute();) { if (response.code() != 200) { throw new SAREFPipelineException("response", "Unexpected response code " + response.code()); } String result = response.body().string(); Document doc = ThemisManager.convertStringToXMLDocument(result); NodeList nodeList = doc.getElementsByTagName("rdf:Description"); ArrayList oopsErrors = new ArrayList(); for (int temp = 0; temp < nodeList.getLength(); temp++) { org.w3c.dom.Node node = nodeList.item(temp); if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { Element element = (Element) node; if (((Element) node).getElementsByTagName("oops:hasCode").item(0) != null) { if (((Element) node).getElementsByTagName("oops:hasName").item(0) != null) { String code = element.getElementsByTagName("oops:hasCode").item(0).getTextContent(); String name = element.getElementsByTagName("oops:hasName").item(0).getTextContent(); String description = element.getElementsByTagName("oops:hasDescription").item(0) .getTextContent(); String affected = ""; NodeList affectedElements = element.getElementsByTagName("oops:hasAffectedElement"); if (affectedElements != null) { for (int k = 0; k < affectedElements.getLength(); k++) { if (k == 0) { affected += "\"" + affectedElements.item(k).getTextContent() + "\""; } else { affected += " ; \"" + affectedElements.item(k).getTextContent() + "\""; } } } String oopsError = String.format( "Code: %s, Name: %s, Description: %s, Affected Elements: %s", code, name, description, affected); oopsErrors.add(oopsError); } else { String code = element.getElementsByTagName("oops:hasCode").item(0).getTextContent(); String description = element.getElementsByTagName("oops:hasDescription").item(0) .getTextContent(); String affected = ""; NodeList affectedElements = element.getElementsByTagName("oops:hasAffectedElement"); if (affectedElements != null) { for (int k = 0; k < affectedElements.getLength(); k++) { if (k == 0) { affected += "\"" + affectedElements.item(k).getTextContent() + "\""; } else { affected += " ; \"" + affectedElements.item(k).getTextContent() + "\""; } } } String oopsError = String.format("Code: %s, Description: %s, Affected Elements: %s", code, description, affected); oopsErrors.add(oopsError); } } } } if (!oopsErrors.isEmpty()) { String data = oopsErrors.stream().map(e -> e.toString()) .collect(Collectors.joining("\n- ", "\n\n- ", "\n\n")); logWarning(getMessage(MESSAGE.oops, data)); } } catch (SocketTimeoutException e) { logWarning(getMessage(MESSAGE.oopsError), e); } } catch (IOException | SAREFPipelineException e) { logWarning(getMessage(MESSAGE.oopsError), e); } } }