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    }