Newer
Older
*
* 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
*
* 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.emse.gitlab.saref.checkers;
Salva5297
committed
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.SocketTimeoutException;
Salva5297
committed
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import fr.emse.gitlab.saref.managers.ThemisManager;
Salva5297
committed
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 fr.emse.gitlab.saref.SAREFPipelineException;
import fr.emse.gitlab.saref.managers.OntologyManager;
import fr.emse.gitlab.saref.managers.RepositoryManager;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.semanticweb.owlapi.reasoner.TimeOutException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
Salva5297
committed
/**
* 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 {
Salva5297
committed
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;
});
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<Explanation<OWLAxiom>> 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<OWLAxiom> generator = ontologyManager.getExplanationGenerator(ontology);
ontology.classesInSignature().forEach(c -> {
return;
}
Set<Explanation<OWLAxiom>> 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);
Salva5297
committed
}
public void checkOops() throws Exception {
Salva5297
committed
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("]]", "] ]");
Salva5297
committed
String xmlRequest = "<?xml version='1.0' encoding='UTF-8'?>" + "<OOPSRequest>" + "<OntologyURI></OntologyURI>"
+ "<OntologyContent><![CDATA[" + onto + "]]></OntologyContent>" + "<Pitfalls></Pitfalls>"
+ "<OutputFormat>RDF/XML</OutputFormat>" + "</OOPSRequest>";
Salva5297
committed
Salva5297
committed
Object[] arrayData = new Object[0];
Salva5297
committed
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();
Salva5297
committed
Response response;
try{
response = httpClient.newCall(request).execute();
catch (SocketTimeoutException e){
Salva5297
committed
httpClient = new OkHttpClient().newBuilder().readTimeout(10, TimeUnit.SECONDS).build();
try{
response = httpClient.newCall(request).execute();
}
catch (SocketTimeoutException f){
httpClient = new OkHttpClient().newBuilder().readTimeout(20, TimeUnit.SECONDS).build();
response = httpClient.newCall(request).execute();
}
Salva5297
committed
}
if (response.code() != 200) {
throw new SAREFPipelineException("response", "Unexpected response code " + response.code());
}
Salva5297
committed
String result = response.body().string();
Salva5297
committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
Document doc = ThemisManager.convertStringToXMLDocument(result);
NodeList nodeList = doc.getElementsByTagName("rdf:Description");
ArrayList<String> oopsErrors = new ArrayList<String>();
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);
}
}
Salva5297
committed
}
}
if (!oopsErrors.isEmpty()) {
String data = oopsErrors.stream().map(e -> e.toString())
.collect(Collectors.joining("\n- ", "\n\n- ", "\n\n"));
logWarning(getMessage(MESSAGE.oops, data));
Salva5297
committed
} catch (IOException | SAREFPipelineException e) {
logWarning(getMessage(MESSAGE.oopsError), e);
Salva5297
committed
}