001 /**
002 * Copyright (C) 2007-2011, 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 */
019
020 package org.dllearner.core.owl;
021
022 import java.io.File;
023 import java.util.HashSet;
024 import java.util.Map;
025 import java.util.Set;
026 import java.util.SortedSet;
027 import java.util.TreeSet;
028
029 import org.dllearner.utilities.owl.OWLAPIAxiomConvertVisitor;
030 import org.semanticweb.owlapi.apibinding.OWLManager;
031 import org.semanticweb.owlapi.model.IRI;
032 import org.semanticweb.owlapi.model.OWLOntology;
033 import org.semanticweb.owlapi.model.OWLOntologyCreationException;
034 import org.semanticweb.owlapi.model.OWLOntologyManager;
035 import org.semanticweb.owlapi.model.OWLOntologyStorageException;
036 import org.semanticweb.owlapi.model.UnknownOWLOntologyException;
037 import org.semanticweb.owlapi.util.SimpleIRIMapper;
038
039 public class KB implements KBElement {
040
041 /**
042 *
043 */
044 private static final long serialVersionUID = -1114373618440145279L;
045 // private Set<Axiom> axioms = new HashSet<Axiom>();
046 private Set<AssertionalAxiom> abox = new HashSet<AssertionalAxiom>();
047 private Set<TerminologicalAxiom> tbox = new HashSet<TerminologicalAxiom>();
048 private Set<PropertyAxiom> rbox = new HashSet<PropertyAxiom>();
049
050 public SortedSet<Individual> findAllIndividuals() {
051 SortedSet<Individual> individuals = new TreeSet<Individual>();
052
053 for(Axiom axiom : abox) {
054 if(axiom instanceof ObjectPropertyAssertion) {
055 individuals.add(((ObjectPropertyAssertion)axiom).getIndividual1());
056 individuals.add(((ObjectPropertyAssertion)axiom).getIndividual2());
057 } else if(axiom instanceof ClassAssertionAxiom) {
058 individuals.add(((ClassAssertionAxiom)axiom).getIndividual());
059 }
060 }
061
062 return individuals;
063 }
064
065 public Set<ObjectProperty> findAllAtomicRoles() {
066 Set<String> roleNames = new HashSet<String>();
067
068 for(Axiom axiom : abox) {
069 if(axiom instanceof ObjectPropertyAssertion)
070 roleNames.add(((ObjectPropertyAssertion)axiom).getRole().getName());
071 }
072
073 for(Axiom axiom : tbox) {
074 if(axiom instanceof SubClassAxiom) {
075 roleNames.addAll(findAllRoleNames(((SubClassAxiom)axiom).getSubConcept()));
076 roleNames.addAll(findAllRoleNames(((SubClassAxiom)axiom).getSuperConcept()));
077 } else if(axiom instanceof EquivalentClassesAxiom) {
078 roleNames.addAll(findAllRoleNames(((EquivalentClassesAxiom)axiom).getConcept1()));
079 roleNames.addAll(findAllRoleNames(((EquivalentClassesAxiom)axiom).getConcept2()));
080 }
081 }
082
083 for(Axiom axiom : rbox) {
084 if(axiom instanceof SymmetricObjectPropertyAxiom)
085 roleNames.add(((SymmetricObjectPropertyAxiom)axiom).getRole().getName());
086 else if(axiom instanceof TransitiveObjectPropertyAxiom)
087 roleNames.add(((TransitiveObjectPropertyAxiom)axiom).getRole().getName());
088 else if(axiom instanceof FunctionalObjectPropertyAxiom)
089 roleNames.add(((FunctionalObjectPropertyAxiom)axiom).getRole().getName());
090 else if(axiom instanceof SubObjectPropertyAxiom) {
091 roleNames.add(((SubObjectPropertyAxiom)axiom).getRole().getName());
092 roleNames.add(((SubObjectPropertyAxiom)axiom).getSubRole().getName());
093 } else if(axiom instanceof InverseObjectPropertyAxiom) {
094 roleNames.add(((InverseObjectPropertyAxiom)axiom).getRole().getName());
095 roleNames.add(((InverseObjectPropertyAxiom)axiom).getInverseRole().getName());
096 }
097 }
098
099 Set<ObjectProperty> ret = new HashSet<ObjectProperty>();
100 for(String name : roleNames) {
101 ret.add(new ObjectProperty(name));
102 }
103 return ret;
104 }
105
106 public Set<String> findAllRoleNames(Description concept) {
107 Set<String> ret = new TreeSet<String>();
108
109 if(concept instanceof ObjectQuantorRestriction)
110 ret.add(((ObjectQuantorRestriction)concept).getRole().getName());
111
112 for(Description child : concept.getChildren())
113 ret.addAll(findAllRoleNames(child));
114
115 return ret;
116 }
117
118 public Set<NamedClass> findAllAtomicConcepts() {
119 // erstmal eine Menge von Konzeptnamen finden, dadurch ist sichergestellt,
120 // dass kein Name zweimal auftaucht (wenn später mal ein Comparator
121 // für Konzepte implementiert ist, dann ist dieser Zwischenschritt
122 // nicht mehr notwendig)
123 Set<String> conceptNames = new HashSet<String>();
124
125 for(Axiom axiom : abox) {
126 if(axiom instanceof ClassAssertionAxiom)
127 conceptNames.addAll(findAllConceptNames(((ClassAssertionAxiom)axiom).getConcept()));
128 }
129
130 for(Axiom axiom : tbox) {
131 if(axiom instanceof SubClassAxiom) {
132 conceptNames.addAll(findAllConceptNames(((SubClassAxiom)axiom).getSubConcept()));
133 conceptNames.addAll(findAllConceptNames(((SubClassAxiom)axiom).getSuperConcept()));
134 } else if(axiom instanceof EquivalentClassesAxiom) {
135 conceptNames.addAll(findAllConceptNames(((EquivalentClassesAxiom)axiom).getConcept1()));
136 conceptNames.addAll(findAllConceptNames(((EquivalentClassesAxiom)axiom).getConcept2()));
137 }
138 }
139
140 Set<NamedClass> ret = new HashSet<NamedClass>();
141 for(String name : conceptNames) {
142 ret.add(new NamedClass(name));
143 }
144
145 return ret;
146 }
147
148 private Set<String> findAllConceptNames(Description concept) {
149 Set<String> ret = new TreeSet<String>();
150
151 if(concept instanceof NamedClass) {
152 ret.add(((NamedClass)concept).getName());
153 }
154
155 for(Description child : concept.getChildren())
156 ret.addAll(findAllConceptNames(child));
157
158 return ret;
159 }
160
161 public Set<AssertionalAxiom> getAbox() {
162 return abox;
163 }
164
165 public Set<PropertyAxiom> getRbox() {
166 return rbox;
167 }
168
169 public Set<TerminologicalAxiom> getTbox() {
170 return tbox;
171 }
172
173 /**
174 * Convenience method, which adds an axiom to ABox, RBox, or
175 * TBox depending on whether it is an assertional, role, or
176 * terminological axiom.
177 *
178 * @param axiom Axiom to add.
179 */
180 public void addAxiom(Axiom axiom) {
181 if(axiom instanceof AssertionalAxiom)
182 addABoxAxiom((AssertionalAxiom) axiom);
183 else if(axiom instanceof PropertyAxiom)
184 addRBoxAxiom((PropertyAxiom) axiom);
185 else if(axiom instanceof TerminologicalAxiom)
186 addTBoxAxiom((TerminologicalAxiom) axiom);
187 else
188 throw new Error(axiom + " has unsupported axiom type.");
189 }
190
191 public void addABoxAxiom(AssertionalAxiom axiom) {
192 abox.add(axiom);
193 }
194
195 public void addTBoxAxiom(TerminologicalAxiom axiom) {
196 tbox.add(axiom);
197 }
198
199 public void addRBoxAxiom(PropertyAxiom axiom) {
200 rbox.add(axiom);
201 }
202
203 /**
204 * Add another knowledge base to this one.
205 * @param kb The knowledge base to add.
206 */
207 public void addKB(KB kb) {
208 for(AssertionalAxiom axiom : kb.getAbox())
209 abox.add(axiom);
210 for(PropertyAxiom axiom : kb.getRbox())
211 rbox.add(axiom);
212 for(TerminologicalAxiom axiom : kb.getTbox())
213 tbox.add(axiom);
214 }
215
216 public int getLength() {
217 int length = 0;
218 for(Axiom a : abox)
219 length += a.getLength();
220 for(Axiom a : tbox)
221 length += a.getLength();
222 for(Axiom a : rbox)
223 length += a.getLength();
224 return length;
225 }
226
227 public String toString(String baseURI, Map<String,String> prefixes) {
228 String str = "TBox["+tbox.size()+"]:\n";
229 for(Axiom a : tbox)
230 str += " " + a.toString(baseURI, prefixes)+"\n";
231 str += "RBox["+rbox.size()+"]:\n";
232 for(Axiom a : rbox)
233 str += " " + a.toString(baseURI, prefixes)+"\n";
234 str += "ABox["+abox.size()+"]:\n";
235 for(Axiom a : abox)
236 str += " " + a.toString(baseURI, prefixes)+"\n";
237 return str;
238 }
239
240 public String toKBSyntaxString(String baseURI, Map<String,String> prefixes) {
241 StringBuffer strbuff = new StringBuffer();
242 strbuff.append("// TBox["+tbox.size()+"]:\n");
243 for(Axiom a : tbox)
244 strbuff.append(" " + a.toKBSyntaxString(baseURI, prefixes)+"\n");
245 strbuff.append("\n// RBox["+rbox.size()+"]:\n");
246 for(Axiom a : rbox)
247 strbuff.append(" " + a.toKBSyntaxString(baseURI, prefixes)+"\n");
248 strbuff.append("\n// ABox["+abox.size()+"]:\n");
249 for(Axiom a : abox)
250 strbuff.append(" " + a.toKBSyntaxString(baseURI, prefixes)+"\n");
251 return strbuff.toString();
252 }
253
254 public Set<Individual> findRelatedIndividuals(Individual individual) {
255 return findRelatedIndividuals(individual, new TreeSet<Individual>());
256 }
257
258 @SuppressWarnings("unchecked")
259 public Set<Individual> findRelatedIndividuals(Individual individual, TreeSet<Individual> searchedIndividuals) {
260 // Individual als durchsucht markieren (wir können nicht davon ausgehen,
261 // dass es sich um einen Individuenbaum handelt, also müssen wir dafür
262 // sorgen, dass jedes Individual nur einmal durchsucht wird)
263 searchedIndividuals.add(individual);
264
265 // alle direkt mit diesem Individual verbundenen Individuals finden
266 TreeSet<Individual> connectedSet = new TreeSet<Individual>();
267 for(AssertionalAxiom axiom : abox) {
268 if(axiom instanceof ObjectPropertyAssertion) {
269 ObjectPropertyAssertion ra = (ObjectPropertyAssertion)axiom;
270 if(ra.getIndividual1().equals(individual))
271 connectedSet.add(ra.getIndividual2());
272 }
273 }
274
275 TreeSet<Individual> connectedSetCopy = (TreeSet<Individual>) connectedSet.clone();
276 // rekursive Aufrufe
277 for(Individual i : connectedSetCopy) {
278 if(!searchedIndividuals.contains(i))
279 connectedSet.addAll(findRelatedIndividuals(i,searchedIndividuals));
280 }
281
282 return connectedSet;
283 }
284
285 public int getNumberOfAxioms() {
286 return (abox.size() + tbox.size() + rbox.size());
287 }
288
289 public void accept(KBElementVisitor visitor) {
290 visitor.visit(this);
291 }
292
293 /**
294 * Returns all axioms in the ontology. Note that calling this
295 * method is not efficient for large knowledge bases, since
296 * internally all axioms are separated into ABox, RBox, and
297 * TBox, which means that a union of these sets is computed
298 * and returned here.
299 *
300 * @return All axioms in the ontology.
301 */
302 public Set<Axiom> getAxioms() {
303 Set<Axiom> axioms = new HashSet<Axiom>();
304 axioms.addAll(abox);
305 axioms.addAll(rbox);
306 axioms.addAll(tbox);
307 return axioms;
308 }
309
310 public void export(File file, org.dllearner.core.OntologyFormat format){
311 OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
312 IRI ontologyIRI = IRI.create("http://example.com");
313 IRI physicalIRI = IRI.create(file.toURI());
314 SimpleIRIMapper mapper = new SimpleIRIMapper(ontologyIRI, physicalIRI);
315 manager.addIRIMapper(mapper);
316 OWLOntology ontology;
317 try {
318 ontology = manager.createOntology(ontologyIRI);
319 // OWLAPIReasoner.fillOWLAPIOntology(manager,ontology,kb);
320 OWLAPIAxiomConvertVisitor.fillOWLOntology(manager, ontology, this);
321 manager.saveOntology(ontology);
322 } catch (OWLOntologyCreationException e) {
323 e.printStackTrace();
324 } catch (UnknownOWLOntologyException e) {
325 e.printStackTrace();
326 } catch (OWLOntologyStorageException e) {
327 e.printStackTrace();
328 }
329 }
330
331 /* (non-Javadoc)
332 * @see org.dllearner.core.owl.KBElement#toManchesterSyntaxString(java.lang.String, java.util.Map)
333 */
334 @Override
335 public String toManchesterSyntaxString(String baseURI, Map<String, String> prefixes) {
336 // TODO Auto-generated method stub
337 return null;
338 }
339 }