001/**
002 * Copyright (C) 2007 - 2016, Jens Lehmann
003 *
004 * This file is part of DL-Learner.
005 *
006 * DL-Learner is free software; you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation; either version 3 of the License, or
009 * (at your option) any later version.
010 *
011 * DL-Learner is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018 */
019package org.dllearner.utilities.owl;
020
021import org.dllearner.reasoning.OWLAPIReasoner;
022import org.semanticweb.owlapi.apibinding.OWLManager;
023import org.semanticweb.owlapi.formats.RDFXMLDocumentFormat;
024import org.semanticweb.owlapi.model.*;
025
026import java.net.URI;
027import java.util.*;
028
029public class OntologyCloserOWLAPI {
030
031        OWLOntology onto;
032        OWLAPIReasoner rs;
033//      ReasonerComponent rs;
034        HashMap<OWLIndividual, Set<OWLObjectExactCardinality>> indToRestr;
035        OWLDataFactory factory;
036        OWLOntologyManager manager;
037        public int numberOfStatementsChanged = 0;
038
039        public OntologyCloserOWLAPI(OWLAPIReasoner reasoner) {
040                this.rs = reasoner;
041                this.indToRestr = new HashMap<>();
042//              this.rs = new ReasonerComponent(reasoner);
043                this.manager = OWLManager.createOWLOntologyManager();
044                this.factory = manager.getOWLDataFactory();
045                this.onto = reasoner.getOntology();
046        }
047
048        /**
049         * counts the number of roles used by each individual and assigns
050         * ExactCardinalityRestriction to Individuals
051         */
052        public void applyNumberRestrictions() {
053                System.out.println("apply ExactCardinalityRestriction to Individuals");
054                Set<OWLObjectProperty> allRoles = this.rs.getObjectProperties();
055                System.out.println("found: " + allRoles.size() + " roles");
056                testForTransitiveProperties(true);
057
058                for (OWLObjectProperty oneRole : allRoles) {
059
060                        Map<OWLIndividual, SortedSet<OWLIndividual>> allRoleMembers = this.rs
061                                        .getPropertyMembers(oneRole);
062                        for (OWLIndividual oneInd : allRoleMembers.keySet()) {
063                                SortedSet<OWLIndividual> fillers = allRoleMembers.get(oneInd);
064                                // only where roles exist
065                                if (fillers.size() > 0) {
066                                        OWLObjectExactCardinality oecr = factory
067                                                        .getOWLObjectExactCardinality(fillers.size(), factory.getOWLObjectProperty(IRI
068                                                                        .create(oneRole.toStringID())), factory.getOWLThing());
069
070                                        OWLAxiom axiom = factory.getOWLClassAssertionAxiom(oecr, factory
071                                                        .getOWLNamedIndividual(IRI.create(oneInd.toStringID())));
072                                        AddAxiom addAxiom = new AddAxiom(this.onto, axiom);
073                                        try {
074                                                // add change
075                                                manager.applyChange(addAxiom);
076                                        } catch (Exception e) {
077                                                e.printStackTrace();
078                                        }
079                                }
080                        }
081
082                }
083
084        }
085
086        /**
087         * counts the number of roles used by each individual and assigns
088         * ExactCardinalityRestriction, but uses only one Intersection: role1
089         * exactly 1 and role2 exactly 2 and ....
090         * 
091         */
092        public void applyNumberRestrictionsConcise() {
093
094                Set<OWLObjectProperty> allRoles = this.rs.getObjectProperties();
095                testForTransitiveProperties(true);
096
097                // collect info for roles and individuals
098                for (OWLObjectProperty oneRole : allRoles) {
099                        Map<OWLIndividual, SortedSet<OWLIndividual>> allRoleMembers = this.rs
100                                        .getPropertyMembers(oneRole);
101                        for (OWLIndividual oneInd : allRoleMembers.keySet()) {
102                                SortedSet<OWLIndividual> fillers = allRoleMembers.get(oneInd);
103                                if (fillers.size() > 0) {
104                                        OWLObjectExactCardinality oecr = factory.getOWLObjectExactCardinality(fillers.size(), factory.getOWLObjectProperty(IRI
105                                                                        .create(oneRole.toStringID())),
106                                                        factory.getOWLThing());
107                                        collectExObjRestrForInd(oneInd, oecr);
108                                }
109                        }
110                }// end for
111
112                Set<OWLClassExpression> target = new HashSet<>();
113                Set<OWLObjectExactCardinality> s = null;
114
115                for (OWLIndividual oneInd : indToRestr.keySet()) {
116                        s = indToRestr.get(oneInd);
117                        for (OWLObjectExactCardinality oecr : s) {
118                                target.add(oecr);
119                        }
120                        // collect everything in an intersection
121                        OWLObjectIntersectionOf intersection = factory.getOWLObjectIntersectionOf(target);
122                        s = null;
123                        target = new HashSet<>();
124
125                        OWLAxiom axiom = factory.getOWLClassAssertionAxiom(intersection, factory
126                                        .getOWLNamedIndividual(IRI.create(oneInd.toStringID())));
127                        AddAxiom addAxiom = new AddAxiom(this.onto, axiom);
128                        try {
129                                manager.applyChange(addAxiom);
130                                numberOfStatementsChanged++;
131                        } catch (Exception e) {
132                                e.printStackTrace();
133                        }
134
135                }// end for
136        }
137
138        /**
139         * @param printflag
140         *            boolean for some output
141         * @return true if some roles are transitive
142         */
143        public boolean testForTransitiveProperties(boolean printflag) {
144
145                Set<OWLTransitiveObjectPropertyAxiom> ax = onto.getAxioms(AxiomType.TRANSITIVE_OBJECT_PROPERTY);
146                boolean retval = !ax.isEmpty();
147                for (OWLPropertyAxiom propertyAxiom : ax) {
148                        if (printflag) {
149                                System.out.println("WARNING transitive object property can't be used in cardinality restriction\n"
150                                                + propertyAxiom.toString() + "but I'm ignoring it");
151                        }
152                }
153                if (printflag) {
154                        System.out.println("No transitive Properties found");
155                }
156                return retval;
157        }
158
159        public void writeOWLFile(URI filename) {
160                try {
161                        manager.saveOntology(this.onto, new RDFXMLDocumentFormat(),
162                                        IRI.create(filename));
163                } catch (Exception e) {
164                        e.printStackTrace();
165                }
166        }
167
168        private boolean collectExObjRestrForInd(OWLIndividual ind,
169                        OWLObjectExactCardinality oecr) {
170                Set<OWLObjectExactCardinality> s = indToRestr.get(ind);
171
172                if (s == null) {
173
174                        indToRestr.put(ind,
175                                        new HashSet<>());
176                        s = indToRestr.get(ind);
177                }
178                return s.add(oecr);
179        }
180
181}