package fr.emse.gitlab.saref.jobs; import java.io.StringWriter; import java.util.Collections; import java.util.Set; import java.util.function.Supplier; import org.apache.jena.query.Dataset; import org.semanticweb.HermiT.ReasonerFactory; import org.semanticweb.owl.explanation.api.Explanation; import org.semanticweb.owl.explanation.api.ExplanationGenerator; import org.semanticweb.owl.explanation.api.ExplanationGeneratorFactory; import org.semanticweb.owl.explanation.impl.blackbox.Configuration; import org.semanticweb.owl.explanation.impl.blackbox.ContractionStrategy; import org.semanticweb.owl.explanation.impl.blackbox.DivideAndConquerContractionStrategy; import org.semanticweb.owl.explanation.impl.blackbox.EntailmentCheckerFactory; import org.semanticweb.owl.explanation.impl.blackbox.ExpansionStrategy; import org.semanticweb.owl.explanation.impl.blackbox.InitialEntailmentCheckStrategy; import org.semanticweb.owl.explanation.impl.blackbox.StructuralTypePriorityExpansionStrategy; import org.semanticweb.owl.explanation.impl.blackbox.checker.BlackBoxExplanationGeneratorFactory; import org.semanticweb.owl.explanation.impl.blackbox.checker.InconsistentOntologyExplanationGeneratorFactory; import org.semanticweb.owl.explanation.impl.blackbox.checker.SatisfiabilityEntailmentCheckerFactory; import org.semanticweb.owlapi.apibinding.OWLManager; import org.semanticweb.owlapi.io.OWLParserFactory; import org.semanticweb.owlapi.model.IRI; import org.semanticweb.owlapi.model.OWLAxiom; import org.semanticweb.owlapi.model.OWLDataFactory; import org.semanticweb.owlapi.model.OWLOntology; import org.semanticweb.owlapi.model.OWLOntologyCreationException; import org.semanticweb.owlapi.model.OWLOntologyManager; import org.semanticweb.owlapi.profiles.OWL2DLProfile; import org.semanticweb.owlapi.profiles.OWLProfileReport; import org.semanticweb.owlapi.profiles.OWLProfileViolation; import org.semanticweb.owlapi.reasoner.OWLReasonerConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.emse.gitlab.saref.SAREFPipelineException; import fr.emse.gitlab.saref.utils.JenaModelOntologyParserFactory; public class CheckOWLProfile extends JobRunner { static final Logger LOG = LoggerFactory.getLogger(CheckOWLProfile.class); public CheckOWLProfile(String testSuiteName) { super(testSuiteName); } public void doJob(Dataset dataset, String ontologyName) throws SAREFPipelineException { LOG.debug("starting " + ontologyName); final OWLDataFactory dataFactory = OWLManager.getOWLDataFactory(); final OWLOntologyManager ontologyManager = OWLManager.createOWLOntologyManager(); OWLParserFactory jenaModelParserFactory = new JenaModelOntologyParserFactory(dataset); Set ontologyParsers = Collections.singleton(jenaModelParserFactory); ontologyManager.setOntologyParsers(ontologyParsers); final Supplier m = () -> ontologyManager; final OWLOntology ontology; try { ontology = ontologyManager.loadOntologyFromOntologyDocument(IRI.create(ontologyName)); } catch (OWLOntologyCreationException ex) { logger.error("Error while loading the ontology in OWLAPI", ex); throw new SAREFPipelineException("Error while loading the ontology in OWLAPI", ex); } final OWLProfileReport report = new OWL2DLProfile().checkOntology(ontology); for (OWLProfileViolation v : report.getViolations()) { logger.warn(v.toString()); } final ReasonerFactory reasonerFactory = new ReasonerFactory(); final InconsistentOntologyExplanationGeneratorFactory inconsistentOntologyExplanationFeneratorFactory = new InconsistentOntologyExplanationGeneratorFactory( reasonerFactory, ontologyManager.getOWLDataFactory(), m, 10000); final ExplanationGenerator gen = inconsistentOntologyExplanationFeneratorFactory .createExplanationGenerator(ontology); final OWLAxiom inc = dataFactory.getOWLSubClassOfAxiom(dataFactory.getOWLThing(), dataFactory.getOWLNothing()); try { final Set> incExplanation = gen.getExplanations(inc, 10); if (!incExplanation.isEmpty()) { StringWriter sw = new StringWriter(); incExplanation.forEach(e -> { sw.append(e.getAxioms().toString()).append("\n"); }); logger.error("The ontology is inconsistent.", "Explanations from OWLApi: " + sw.toString()); throw new SAREFPipelineException("The ontology is inconsistent.", "Explanations from OWLApi: " + sw.toString()); } } catch (Exception ex) { logger.error("Error while reasoning with the ontology", ex); throw new SAREFPipelineException("Error while reasoning with the ontology", ex); } final EntailmentCheckerFactory checker = new SatisfiabilityEntailmentCheckerFactory(reasonerFactory, m); final ExpansionStrategy expansionStrategy = new StructuralTypePriorityExpansionStrategy<>( InitialEntailmentCheckStrategy.PERFORM, m); final ContractionStrategy contractionStrategy = new DivideAndConquerContractionStrategy<>(); final Configuration config = new Configuration<>(checker, expansionStrategy, contractionStrategy, null, m); final ExplanationGeneratorFactory explanationGeneratorFactory = new BlackBoxExplanationGeneratorFactory( config); final ExplanationGenerator fgen = explanationGeneratorFactory.createExplanationGenerator(ontology); ontology.classesInSignature().forEach(c -> { OWLAxiom axiom = dataFactory.getOWLSubClassOfAxiom(c, dataFactory.getOWLNothing()); Set> explanation = fgen.getExplanations(axiom, 10); if (!explanation.isEmpty()) { StringWriter sw = new StringWriter(); explanation.forEach(e -> { sw.append(e.getAxioms().toString()).append("\n"); }); logger.warn(String.format("Class %s cannot be satisfied.", c), "Explanations from OWLApi " + sw.toString()); } }); } }