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.reasoning;
021
022 import java.io.File;
023 import java.io.IOException;
024 import java.net.MalformedURLException;
025 import java.net.URI;
026 import java.net.URL;
027 import java.util.Collection;
028 import java.util.HashMap;
029 import java.util.HashSet;
030 import java.util.LinkedList;
031 import java.util.Map;
032 import java.util.Set;
033 import java.util.SortedSet;
034 import java.util.TreeMap;
035 import java.util.TreeSet;
036
037 import javax.xml.namespace.QName;
038
039 import org.apache.xmlbeans.XmlCursor;
040 import org.dllearner.core.ComponentInitException;
041 import org.dllearner.core.AbstractKnowledgeSource;
042 import org.dllearner.core.OntologyFormat;
043 import org.dllearner.core.AbstractReasonerComponent;
044 import org.dllearner.core.configurators.DIGReasonerConfigurator;
045 import org.dllearner.core.options.BooleanConfigOption;
046 import org.dllearner.core.options.ConfigEntry;
047 import org.dllearner.core.options.ConfigOption;
048 import org.dllearner.core.options.InvalidConfigOptionValueException;
049 import org.dllearner.core.options.StringConfigOption;
050 import org.dllearner.core.owl.ClassHierarchy;
051 import org.dllearner.core.owl.Description;
052 import org.dllearner.core.owl.Individual;
053 import org.dllearner.core.owl.NamedClass;
054 import org.dllearner.core.owl.Nothing;
055 import org.dllearner.core.owl.ObjectProperty;
056 import org.dllearner.core.owl.ObjectPropertyHierarchy;
057 import org.dllearner.core.owl.Thing;
058 import org.dllearner.utilities.Files;
059 import org.dllearner.utilities.Helper;
060 import org.dllearner.utilities.owl.ConceptComparator;
061 import org.dllearner.utilities.owl.RoleComparator;
062 import org.kr.dl.dig.v1_1.Concepts;
063 import org.kr.dl.dig.v1_1.Csynonyms;
064 import org.kr.dl.dig.v1_1.IdType;
065 import org.kr.dl.dig.v1_1.Named;
066 import org.kr.dl.dig.v1_1.ResponseDocument;
067 import org.kr.dl.dig.v1_1.ResponsesDocument;
068 import org.kr.dl.dig.v1_1.Roles;
069 import org.kr.dl.dig.v1_1.Rsynonyms;
070 import org.kr.dl.dig.v1_1.IndividualSetDocument.IndividualSet;
071
072 /**
073 * DIG 1.1 implementation of the reasoner interface.
074 *
075 * @author Jens Lehmann
076 *
077 */
078 public class DIGReasoner extends AbstractReasonerComponent {
079
080 private DIGReasonerConfigurator configurator;
081 @Override
082 public DIGReasonerConfigurator getConfigurator(){
083 return configurator;
084 }
085
086
087 URL reasonerURL;
088
089 // Variablen für Reasoner
090 DIGHTTPConnector connector;
091 String identifier;
092 URI kbURI;
093 private String asksPrefix;
094 // Cache für Konzepte, Rollen und Individuen
095 Set<NamedClass> atomicConcepts;
096 Set<ObjectProperty> atomicRoles;
097 SortedSet<Individual> individuals;
098
099 // Cache für Subsumptionhierarchie
100 // Comparator ist notwendig, da sonst z.B. verschiedene Instanzen des
101 // atomaren Konzepts male
102 // unterschiedlich sind;
103 // alternativ wäre auch eine Indizierung über Strings möglich
104 ConceptComparator conceptComparator = new ConceptComparator();
105 RoleComparator roleComparator = new RoleComparator();
106 ClassHierarchy subsumptionHierarchy;
107 ObjectPropertyHierarchy roleHierarchy;
108 // enthält atomare Konzepte, sowie Top und Bottom
109 Set<Description> allowedConceptsInSubsumptionHierarchy;
110
111 private boolean writeDIGProtocol;
112 private File digProtocolFile;
113 private static String defaultDIGProtocolFile = "log/digProtocol.txt";
114
115
116
117 public DIGReasoner(Set<AbstractKnowledgeSource> sources) {
118 super(sources);
119 this.configurator = new DIGReasonerConfigurator(this);
120 try {
121 reasonerURL = new URL("http://localhost:8081");
122 } catch (MalformedURLException e) {
123 }
124 }
125
126 @Override
127 public void init() throws ComponentInitException {
128 // if a DIG protocol is written clear the file first
129 if(writeDIGProtocol) {
130 if(digProtocolFile == null)
131 digProtocolFile = new File(defaultDIGProtocolFile);
132 Files.clearFile(digProtocolFile);
133 connector = new DIGHTTPConnector(reasonerURL, digProtocolFile);
134 } else {
135 connector = new DIGHTTPConnector(reasonerURL);
136 }
137
138 try {
139 identifier = connector.getIdentifier();
140 } catch (IOException e1) {
141 throw new ComponentInitException("Communication problem with DIG Reasoner. Please make sure there is a DIG reasoner running at " + reasonerURL + " and try again.", e1);
142 }
143 kbURI = connector.newKB();
144
145 // asks-Prefix entsprechend der KB-URI initialisieren
146 asksPrefix = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
147 asksPrefix += "<asks xmlns=\"http://dl.kr.org/dig/2003/02/lang\" "
148 + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
149 + "xsi:schemaLocation=\"http://dl.kr.org/dig/2003/02/lang\n"
150 + "http://dl-web.man.ac.uk/dig/2003/02/dig.xsd\" uri=\"" + kbURI + "\">";
151
152 // momementan wird davon ausgegangen, dass toDIG(kbURI) den gesamten
153 // tells-Request liefert
154 StringBuilder sb = new StringBuilder();
155 // sb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
156 // sb.append("<tells xmlns=\"http://dl.kr.org/dig/2003/02/lang\" " +
157 // "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
158 // "xsi:schemaLocation=\"http://dl.kr.org/dig/2003/02/lang\n" +
159 // "http://dl-web.man.ac.uk/dig/2003/02/dig.xsd\" uri=\""+kbURI+"\">");
160 for (AbstractKnowledgeSource source : sources) {
161 sb.append(source.toDIG(kbURI));
162
163 ResponseDocument rd = null;
164 try {
165 rd = connector.tells(sb.toString());
166 } catch (IOException e) {
167 throw new ComponentInitException("Could not read knowledge source " + source + ".", e);
168 }
169 if (!rd.getResponse().isSetOk()) {
170 System.err.println("DIG-Reasoner cannot read knowledgebase.");
171 System.exit(0);
172 }
173 }
174 // sb.append("</tells>");
175
176 // DIG-Abfragen nach Konzepten, Rollen, Individuals
177 atomicConcepts = getAtomicConceptsDIG();
178 atomicRoles = getAtomicRolesDIG();
179 individuals = getIndividualsDIG();
180
181 }
182
183 public static String getName() {
184 return "DIG reasoner";
185 }
186
187
188 public static Collection<ConfigOption<?>> createConfigOptions() {
189 Collection<ConfigOption<?>> options = new LinkedList<ConfigOption<?>>();
190 options.add(new StringConfigOption("reasonerUrl", "URL of the DIG reasoner"));
191 options.add(new BooleanConfigOption("writeDIGProtocol",
192 "specifies whether or not to write a protocoll of send and received DIG requests",
193 false));
194 options.add(new StringConfigOption("digProtocolFile", "the file to store the DIG protocol",
195 defaultDIGProtocolFile));
196 return options;
197 }
198
199 /*
200 * (non-Javadoc)
201 *
202 * @see org.dllearner.core.Component#applyConfigEntry(org.dllearner.core.ConfigEntry)
203 */
204 @Override
205 public <T> void applyConfigEntry(ConfigEntry<T> entry) throws InvalidConfigOptionValueException {
206 String name = entry.getOptionName();
207 if (name.equals("reasonerUrl")) {
208 String s = (String) entry.getValue();
209 try {
210 reasonerURL = new URL(s);
211 } catch (MalformedURLException e) {
212 // e.printStackTrace();
213 throw new InvalidConfigOptionValueException(entry.getOption(), entry.getValue());
214 }
215 } else if(name.equals("writeDIGProtocol")) {
216 writeDIGProtocol = (Boolean) entry.getValue();
217 } else if(name.equals("digProtocolFile")) {
218 digProtocolFile = new File((String) entry.getValue());
219 }
220 }
221
222 /**
223 * Construct a subsumption hierarchy using DIG queries. After calling this
224 * method one can ask for children or parents in the subsumption hierarchy.
225 */
226 // public void prepareSubsumptionHierarchy(Set<NamedClass> allowedConcepts) {
227 // allowedConceptsInSubsumptionHierarchy = new TreeSet<Description>(conceptComparator);
228 // allowedConceptsInSubsumptionHierarchy.addAll(allowedConcepts);
229 // allowedConceptsInSubsumptionHierarchy.add(new Thing());
230 // allowedConceptsInSubsumptionHierarchy.add(new Nothing());
231 //
232 // TreeMap<Description, TreeSet<Description>> subsumptionHierarchyUp = new TreeMap<Description, TreeSet<Description>>(
233 // conceptComparator);
234 // TreeMap<Description, TreeSet<Description>> subsumptionHierarchyDown = new TreeMap<Description, TreeSet<Description>>(
235 // conceptComparator);
236 //
237 // // Subsumptionhierarchy berechnen
238 // // TODO: kann man effizienter auch in einer Abfrage machen
239 //
240 // // Refinements von Top
241 // TreeSet<Description> tmp = getMoreSpecialConceptsDIG(new Thing());
242 // tmp.retainAll(allowedConceptsInSubsumptionHierarchy);
243 // subsumptionHierarchyDown.put(new Thing(), tmp);
244 //
245 // // Refinements von Bottom
246 // tmp = getMoreGeneralConceptsDIG(new Nothing());
247 // tmp.retainAll(allowedConceptsInSubsumptionHierarchy);
248 // subsumptionHierarchyUp.put(new Nothing(), tmp);
249 //
250 // // Refinement atomarer Konzepte
251 // for (NamedClass atom : atomicConcepts) {
252 // tmp = getMoreSpecialConceptsDIG(atom);
253 // tmp.retainAll(allowedConceptsInSubsumptionHierarchy);
254 // subsumptionHierarchyDown.put(atom, tmp);
255 //
256 // tmp = getMoreGeneralConceptsDIG(atom);
257 // tmp.retainAll(allowedConceptsInSubsumptionHierarchy);
258 // subsumptionHierarchyUp.put(atom, tmp);
259 // }
260 //
261 // subsumptionHierarchy = new ClassHierarchy(
262 // subsumptionHierarchyUp, subsumptionHierarchyDown);
263 // }
264
265 /**
266 * Constructs a role hierarchy using DIG queries. After calling this method,
267 * one can query parents or children of roles.
268 *
269 * TODO Does not yet take ignored roles into account.
270 */
271 // public void prepareRoleHierarchy(Set<ObjectProperty> allowedRoles) {
272 // TreeMap<ObjectProperty, TreeSet<ObjectProperty>> roleHierarchyUp = new TreeMap<ObjectProperty, TreeSet<ObjectProperty>>(
273 // roleComparator);
274 // TreeMap<ObjectProperty, TreeSet<ObjectProperty>> roleHierarchyDown = new TreeMap<ObjectProperty, TreeSet<ObjectProperty>>(
275 // roleComparator);
276 //
277 // // Refinement atomarer Konzepte
278 // for (ObjectProperty role : atomicRoles) {
279 // roleHierarchyDown.put(role, getMoreSpecialRolesDIG(role));
280 // roleHierarchyUp.put(role, getMoreGeneralRolesDIG(role));
281 // }
282 //
283 // roleHierarchy = new ObjectPropertyHierarchy(allowedRoles, roleHierarchyUp,
284 // roleHierarchyDown);
285 // }
286
287 // eigentlich müsste man klonen um sicherzustellen, dass der parent-Link
288 // bei null bleibt; bei der aktuellen Implementierung ist der parent-Link
289 // nicht immer null, was bei GP negative Auswirkungen haben könnte
290 // Update: wird durch klonen innerhalb der GP-Operationen erledigt
291 public Set<NamedClass> getNamedClasses() {
292 /*
293 * if(Config.algorithm == Config.Algorithm.GP || Config.algorithm ==
294 * Config.Algorithm.HYBRID_GP) { Set<AtomicConcept> returnSet = new
295 * HashSet<AtomicConcept>(); for(AtomicConcept ac : atomicConcepts)
296 * returnSet.add((AtomicConcept)ac.clone()); return returnSet; }
297 */
298 return atomicConcepts;
299 }
300
301 private Set<NamedClass> getAtomicConceptsDIG() {
302 String atomicConceptsDIG = asksPrefix;
303 atomicConceptsDIG += "<allConceptNames id=\"ask_names\"/></asks>";
304
305 ResponsesDocument rd = connector.asks(atomicConceptsDIG);
306 // Struktur: einzelnes conceptSet auÃen, dann mehrere synonyms, die dann
307 // die Konzept inkl. Top und Bottom enthalten
308 Csynonyms[] synonymsArray = rd.getResponses().getConceptSetArray();
309 Concepts[] conceptsArray = synonymsArray[0].getSynonymsArray();
310
311 Set<NamedClass> atomicConcepts = new TreeSet<NamedClass>(conceptComparator);
312 for (Concepts concepts : conceptsArray) {
313 boolean topOrBottomFound = false;
314 if (concepts.getBottomArray().length != 0 || concepts.getTopArray().length != 0)
315 topOrBottomFound = true;
316
317 // nur weitersuchen falls das Konzept nicht äquivalent zu Top
318 // oder Bottom ist
319 if (!topOrBottomFound) {
320 boolean nonAnonymousConceptFound = false;
321 NamedClass foundConcept = null;
322 Named[] catoms = concepts.getCatomArray();
323 for (Named catom : catoms) {
324 String name = catom.getName();
325 if (!name.startsWith("anon")) {
326 if (!nonAnonymousConceptFound) {
327 nonAnonymousConceptFound = true;
328 foundConcept = new NamedClass(catom.getName());
329 atomicConcepts.add(foundConcept);
330 } else {
331 System.out
332 .println("Warning: Background knowledge contains synonym concepts. "
333 + "We decide to pick "
334 + foundConcept
335 + ". \nDIG-XML:\n" + concepts);
336 }
337 }
338 }
339 }
340 }
341
342 return atomicConcepts;
343 }
344
345 public Set<ObjectProperty> getObjectProperties() {
346 return atomicRoles;
347 }
348
349 private Set<ObjectProperty> getAtomicRolesDIG() {
350 String atomicRolesDIG = asksPrefix;
351 atomicRolesDIG += "<allRoleNames id=\"ask_roles\"/></asks>";
352
353 ResponsesDocument rd = connector.asks(atomicRolesDIG);
354 // Struktur: einzelnes roleSet auÃen, dann synonyms mit ratoms
355 // innen
356 Rsynonyms[] synonymsArray = rd.getResponses().getRoleSetArray();
357 Roles[] rolesArray = synonymsArray[0].getSynonymsArray();
358
359 Set<ObjectProperty> digAtomicRoles = new HashSet<ObjectProperty>();
360 for (Roles roles : rolesArray) {
361 // hier koennen wiederum mehrere ratoms enthalten sein,
362 // aber wir wollen nur eins auslesen
363 Named[] ratoms = roles.getRatomArray();
364 Named role = ratoms[0];
365 digAtomicRoles.add(new ObjectProperty(role.getName()));
366
367 if (ratoms.length > 1)
368 System.out.println("Warning: Background knowledge contains synonym roles. "
369 + "Will ignore all but the first. \nDIG-XML:\n" + roles);
370 }
371
372 return digAtomicRoles;
373 }
374
375 public SortedSet<Individual> getIndividuals() {
376 return individuals;
377 }
378
379 private SortedSet<Individual> getIndividualsDIG() {
380 String individualsDIG = asksPrefix;
381 individualsDIG += "<allIndividuals id=\"ask_individuals\"/></asks>";
382
383 ResponsesDocument rd = connector.asks(individualsDIG);
384 // Struktur: einzelnes individualSet auÃen, dann Liste von
385 // individual-Elementen
386 IndividualSet[] individualsArray = rd.getResponses().getIndividualSetArray();
387 Named[] namedIndividuals = individualsArray[0].getIndividualArray();
388
389 SortedSet<Individual> digIndividuals = new TreeSet<Individual>();
390 for (Named named : namedIndividuals)
391 digIndividuals.add(new Individual(named.getName()));
392
393 return digIndividuals;
394 }
395
396 @Override
397 public ReasonerType getReasonerType() {
398 return ReasonerType.DIG;
399 }
400
401 @Override
402 public boolean isSuperClassOfImpl(Description superConcept, Description subConcept) {
403 // System.out.println("subsumes(" + superConcept + "," + subConcept +
404 // ")");
405 String subsumesDIG = asksPrefix;
406 subsumesDIG += "<subsumes id=\"query_subsume\">";
407 subsumesDIG += DIGConverter.getDIGString(superConcept);
408 subsumesDIG += DIGConverter.getDIGString(subConcept);
409 subsumesDIG += "</subsumes></asks>";
410
411 return parseBooleanAnswer(subsumesDIG);
412 }
413
414 // @Override
415 // public Set<Description> subsumesImpl(Description superConcept, Set<Description> subConcepts) {
416 // String subsumesDIG = asksPrefix;
417 // int id = 0;
418 // // ID-Konzept-Zuordnung speichern, da bei der Antwort nur die IDs
419 // // ausgegeben werden
420 // Map<String, Description> queryMap = new HashMap<String, Description>();
421 // for (Description subConcept : subConcepts) {
422 // queryMap.put("query" + id, subConcept);
423 // subsumesDIG += "<subsumes id=\"query" + id + "\">";
424 // subsumesDIG += DIGConverter.getDIGString(superConcept);
425 // subsumesDIG += DIGConverter.getDIGString(subConcept);
426 // subsumesDIG += "</subsumes>";
427 // id++;
428 // }
429 // subsumesDIG += "</asks>";
430 //
431 // ResponsesDocument rd = connector.asks(subsumesDIG);
432 // IdType[] subsumedConceptsIds = rd.getResponses().getTrueArray();
433 //
434 // Set<Description> returnSet = new HashSet<Description>();
435 // for (IdType idType : subsumedConceptsIds) {
436 // returnSet.add(queryMap.get(idType.getId()));
437 // }
438 // return returnSet;
439 // }
440
441 @Override
442 public Set<Description> isSuperClassOfImpl(Set<Description> superConcepts, Description subConcept) {
443 String subsumesDIG = asksPrefix;
444 int id = 0;
445 Map<String, Description> queryMap = new HashMap<String, Description>();
446 for (Description superConcept : superConcepts) {
447 queryMap.put("query" + id, superConcept);
448 subsumesDIG += "<subsumes id=\"query" + id + "\">";
449 subsumesDIG += DIGConverter.getDIGString(superConcept);
450 subsumesDIG += DIGConverter.getDIGString(subConcept);
451 subsumesDIG += "</subsumes>";
452 id++;
453 }
454 subsumesDIG += "</asks>";
455
456 ResponsesDocument rd = connector.asks(subsumesDIG);
457 IdType[] subsumedConceptsIds = rd.getResponses().getTrueArray();
458
459 Set<Description> returnSet = new HashSet<Description>();
460 for (IdType idType : subsumedConceptsIds) {
461 returnSet.add(queryMap.get(idType.getId()));
462 }
463 return returnSet;
464 }
465
466 /*
467 * // es wird geklont, damit Subsumptionhierarchie nicht von auÃen verändert
468 * werden // kann @SuppressWarnings("unchecked") @Override public SortedSet<Concept>
469 * getMoreGeneralConcepts(Concept concept) { return (TreeSet<Concept>)
470 * subsumptionHierarchyUp.get(concept).clone(); // return
471 * subsumptionHierarchyUp.get(concept); // ohne klonen geht es nicht }
472 *
473 * @SuppressWarnings("unchecked") @Override public SortedSet<Concept>
474 * getMoreSpecialConcepts(Concept concept) { return (TreeSet<Concept>)
475 * subsumptionHierarchyDown.get(concept).clone(); // return
476 * subsumptionHierarchyDown.get(concept); // ohne klonen geht es nicht }
477 */
478
479 // @Override
480 // public ObjectPropertyHierarchy getRoleHierarchy() {
481 // return roleHierarchy;
482 // }
483
484 @Override
485 protected TreeSet<Description> getSuperClassesImpl(Description concept) {
486 String moreGeneralDIG = asksPrefix;
487 moreGeneralDIG += "<parents id=\"query_parents\">";
488 moreGeneralDIG += DIGConverter.getDIGString(concept);
489 moreGeneralDIG += "</parents></asks>";
490
491 ResponsesDocument rd = connector.asks(moreGeneralDIG);
492 TreeSet<Description> resultsSet = new TreeSet<Description>(conceptComparator);
493 // ein Array, der Synomyms-Elemente enthält, die dann Mengen von
494 // äquivalenten Konzepten enthalten;
495 // (es wird hier nur das erste Element des ConceptSetArrays gelesen,
496 // da nur ein solches Element bei dieser Abfrage erwartet wird)
497 Concepts[] conceptsArray = rd.getResponses().getConceptSetArray()[0].getSynonymsArray();
498
499 for (int i = 0; i < conceptsArray.length; i++) {
500 // es werden nur atomare Konzepte erwartet
501 Named[] atoms = conceptsArray[i].getCatomArray();
502
503 for (Named atom : atoms) {
504 NamedClass ac = new NamedClass(atom.getName());
505 if (allowedConceptsInSubsumptionHierarchy.contains(ac))
506 resultsSet.add(ac);
507 }
508
509 // hinzufügen von Top, falls notwendig
510 if (conceptsArray[i].getTopArray().length > 0)
511 resultsSet.add(new Thing());
512
513 // falls bisher kein erlaubtes Konzept gefunden wurden, dann gibt es
514 // entweder keine allgemeineren Konzepte oder es handelt sich um
515 // nicht erlaubte (von Jena erzeugte) Konzepte, die nicht äquivalent
516 // zu einem erlaubten Konzept sind; in dem Fall muss die Methode
517 // rekursiv
518 // noch einmal aufgerufen werden
519 if (resultsSet.size() == 0 && atoms.length > 0) {
520 // wir wählen das erste Konzept aus, welches ein ignoriertes
521 // Konzept ist
522 // (sonst wäre es weiter oben gefunden wurden)
523 NamedClass ignoredAtomicConcept = new NamedClass(atoms[0].getName());
524 resultsSet.addAll(getSuperClassesImpl(ignoredAtomicConcept));
525 }
526
527 }
528
529 return resultsSet;
530 }
531
532 @Override
533 protected TreeSet<Description> getSubClassesImpl(Description concept) {
534 String moreSpecialDIG = asksPrefix;
535 moreSpecialDIG += "<children id=\"query_children\">";
536 moreSpecialDIG += DIGConverter.getDIGString(concept);
537 moreSpecialDIG += "</children></asks>";
538
539 // Kommentare siehe getMoreGeneralConcepts(Concept)
540 ResponsesDocument rd = connector.asks(moreSpecialDIG);
541 TreeSet<Description> resultsSet = new TreeSet<Description>(conceptComparator);
542 Concepts[] conceptsArray = rd.getResponses().getConceptSetArray()[0].getSynonymsArray();
543
544 for (int i = 0; i < conceptsArray.length; i++) {
545 Named[] atoms = conceptsArray[i].getCatomArray();
546 for (Named atom : atoms) {
547 NamedClass ac = new NamedClass(atom.getName());
548 if (allowedConceptsInSubsumptionHierarchy.contains(ac))
549 resultsSet.add(ac);
550 }
551
552 // hinzufügen von Bottom, falls notwendig
553 if (conceptsArray[i].getBottomArray().length > 0)
554 resultsSet.add(new Nothing());
555
556 if (resultsSet.size() == 0 && atoms.length > 0) {
557 NamedClass ignoredAtomicConcept = new NamedClass(atoms[0].getName());
558 resultsSet.addAll(getSubClassesImpl(ignoredAtomicConcept));
559 }
560 }
561
562 return resultsSet;
563 }
564
565 @Override
566 protected TreeSet<ObjectProperty> getSuperPropertiesImpl(ObjectProperty role) {
567 String moreGeneralRolesDIG = asksPrefix;
568 moreGeneralRolesDIG += "<rparents id=\"query_parents\">";
569 moreGeneralRolesDIG += "<ratom name=\"" + role.getName() + "\" />";
570 moreGeneralRolesDIG += "</rparents></asks>";
571
572 ResponsesDocument rd = connector.asks(moreGeneralRolesDIG);
573 TreeSet<ObjectProperty> resultsSet = new TreeSet<ObjectProperty>(roleComparator);
574 Roles[] rolesArray = rd.getResponses().getRoleSetArray()[0].getSynonymsArray();
575
576 for (int i = 0; i < rolesArray.length; i++) {
577 Named[] atoms = rolesArray[i].getRatomArray();
578
579 for (Named atom : atoms) {
580 ObjectProperty ar = new ObjectProperty(atom.getName());
581 // if(Config.Refinement.allowedRoles.contains(ar))
582 resultsSet.add(ar);
583 }
584 }
585
586 // System.out.println(rd);
587
588 return resultsSet;
589 }
590
591 @Override
592 protected TreeSet<ObjectProperty> getSubPropertiesImpl(ObjectProperty role) {
593 String moreSpecialRolesDIG = asksPrefix;
594 moreSpecialRolesDIG += "<rchildren id=\"query_children\">";
595 moreSpecialRolesDIG += "<ratom name=\"" + role.getName() + "\" />";
596 moreSpecialRolesDIG += "</rchildren></asks>";
597
598 ResponsesDocument rd = connector.asks(moreSpecialRolesDIG);
599 TreeSet<ObjectProperty> resultsSet = new TreeSet<ObjectProperty>(roleComparator);
600 Roles[] rolesArray = rd.getResponses().getRoleSetArray()[0].getSynonymsArray();
601
602 for (int i = 0; i < rolesArray.length; i++) {
603 Named[] atoms = rolesArray[i].getRatomArray();
604
605 for (Named atom : atoms) {
606 ObjectProperty ar = new ObjectProperty(atom.getName());
607 // if(Config.Refinement.allowedRoles.contains(ar))
608 resultsSet.add(ar);
609 }
610 }
611
612 return resultsSet;
613 }
614
615 @Override
616 public boolean hasTypeImpl(Description concept, Individual individual) {
617 String instanceCheckDIG = asksPrefix;
618 instanceCheckDIG += "<instance id= \"query_instance\">";
619 instanceCheckDIG += "<individual name=\"" + individual.getName() + "\"/>";
620 instanceCheckDIG += DIGConverter.getDIGString(concept);
621 instanceCheckDIG += "</instance></asks>";
622
623 return parseBooleanAnswer(instanceCheckDIG);
624 }
625
626 @Override
627 public SortedSet<Individual> hasTypeImpl(Description concept, Set<Individual> individuals) {
628 String instanceCheckDIG = asksPrefix;
629 int id = 0;
630 // ID-Konzept-Zuordnung speichern, da bei der Antwort nur die IDs
631 // ausgegeben werden
632 Map<String, String> queryMap = new HashMap<String, String>();
633 for (Individual individual : individuals) {
634 queryMap.put("query" + id, individual.getName());
635 instanceCheckDIG += "<instance id= \"query" + id + "\">";
636 instanceCheckDIG += "<individual name=\"" + individual.getName() + "\"/>";
637 instanceCheckDIG += DIGConverter.getDIGString(concept);
638 instanceCheckDIG += "</instance>";
639 id++;
640 }
641 instanceCheckDIG += "</asks>";
642
643 ResponsesDocument rd = connector.asks(instanceCheckDIG);
644 IdType[] ids = rd.getResponses().getTrueArray();
645
646 SortedSet<Individual> returnSet = new TreeSet<Individual>();
647 for (IdType idType : ids) {
648 returnSet.add(new Individual(queryMap.get(idType.getId())));
649 }
650 return returnSet;
651 }
652
653 @Override
654 public SortedSet<Individual> getIndividualsImpl(Description concept) {
655
656 String retrievalDIG = asksPrefix;
657 retrievalDIG += "<instances id= \"query_instance\">";
658 retrievalDIG += DIGConverter.getDIGString(concept);
659 retrievalDIG += "</instances></asks>";
660
661 ResponsesDocument rd = connector.asks(retrievalDIG);
662 // System.out.println(rd);
663 Named[] individuals = rd.getResponses().getIndividualSetArray()[0].getIndividualArray();
664
665 SortedSet<Individual> results = new TreeSet<Individual>();
666 for (Named individual : individuals)
667 results.add(new Individual(individual.getName()));
668 return results;
669 }
670
671 // ToDo: gibt momentan nur einen Wert bei äquivalenten Klassen aus
672 @Override
673 public Set<NamedClass> getTypesImpl(Individual individual) {
674 String typesDIG = asksPrefix;
675 typesDIG += "<types id=\"query_types\">";
676 typesDIG += "<individual name=\"" + individual.getName() + "\" />";
677 typesDIG += "</types></asks>";
678
679 ResponsesDocument rd = connector.asks(typesDIG);
680 TreeSet<NamedClass> resultsSet = new TreeSet<NamedClass>(conceptComparator);
681 Concepts[] conceptsArray = rd.getResponses().getConceptSetArray()[0].getSynonymsArray();
682
683 for (int i = 0; i < conceptsArray.length; i++) {
684 Named[] atoms = conceptsArray[i].getCatomArray();
685 for (Named atom : atoms) {
686 NamedClass ac = new NamedClass(atom.getName());
687 if (allowedConceptsInSubsumptionHierarchy.contains(ac))
688 // if(Config.Refinement.allowedConcepts.contains(ac))
689 resultsSet.add(ac);
690 }
691 }
692
693 // System.out.println("document:");
694 // System.out.println(rd);
695 // System.out.println("parsed:");
696 // System.out.println(resultsSet);
697
698 return resultsSet;
699 }
700
701 // es sieht so aus, als ob die XSD-Datei kaputt ist - es gibt zumindest
702 // keine getter um ein IndividualPairSet zu finden; in der XSD-Datei ist
703 // das in Responsegroup auch nicht definiert
704 // => deswegen wird hier die XML-Cursor-API verwendet
705 @Override
706 public Map<Individual, SortedSet<Individual>> getPropertyMembersImpl(ObjectProperty atomicRole) {
707 String relatedIndividualsDIG = asksPrefix;
708 relatedIndividualsDIG += "<relatedIndividuals id=\"related_individuals\">";
709 relatedIndividualsDIG += "<ratom name=\"" + atomicRole.getName() + "\" />";
710 relatedIndividualsDIG += "</relatedIndividuals></asks>";
711
712 ResponsesDocument rd = connector.asks(relatedIndividualsDIG);
713 Map<Individual, SortedSet<Individual>> resultMap = new TreeMap<Individual, SortedSet<Individual>>();
714
715 QName name = new QName("name");
716 XmlCursor cursor = rd.newCursor();
717 cursor.toFirstChild(); // Responses
718 cursor.toFirstChild(); // IndividualPairSet
719
720 int childNumber = 0;
721 Individual ind1;
722 Individual ind2;
723
724 // so lange noch Kinder existieren
725 while (cursor.toChild(childNumber)) {
726 // Cursor steht jetzt bei einem IndividualPair
727 cursor.toFirstChild();
728 // jetzt steht er bei einem Individual, dessen Namen wir auslesen
729 // können
730 ind1 = new Individual(cursor.getAttributeText(name).toString());
731 cursor.toNextSibling();
732 ind2 = new Individual(cursor.getAttributeText(name).toString());
733
734 Helper.addMapEntry(resultMap, ind1, ind2);
735
736 // Cursor wieder hoch auf IndividualPairSet bewegen
737 cursor.toParent();
738 cursor.toParent();
739 childNumber++;
740 }
741
742 /*
743 * System.out.println("document:"); System.out.println(rd);
744 * System.out.println("parsed:"); System.out.println(resultMap);
745 */
746
747 return resultMap;
748 }
749
750 @Override
751 public boolean isSatisfiableImpl() {
752 String satisfiableDIG = asksPrefix;
753 // wenn Top erfüllbar ist, dann gibt es auch ein Modell für die KB
754 // (satisfiability für KB ist nicht Teil von DIG 1.1)
755 satisfiableDIG += "<satisfiable id=\"query_satisfiable\"><top/></satisfiable>";
756 satisfiableDIG += "</asks>";
757
758 return parseBooleanAnswer(satisfiableDIG);
759 }
760
761 private boolean parseBooleanAnswer(String asks) {
762 ResponsesDocument rd = connector.asks(asks);
763 if (rd.getResponses().getTrueArray().length == 1)
764 return true;
765 else
766 return false;
767 }
768
769 public String getIdentifier() {
770 return identifier;
771 }
772
773 @Override
774 public void releaseKB() {
775 connector.releaseKB(kbURI);
776 }
777
778 // TODO: not working yet - it is probably better to include a method
779 // in knowledge source to save the corresponding source to a file
780 public void saveOntology(File file, OntologyFormat format) {
781 // KAON2-Reasoner erzeugen und den die Ontologie speichern lassen
782 // (später könnte man das über Jena erledigen, allerdings funktioniert
783 // das mit KAON2 auch gut)
784 // KAON2Reasoner kaon2Reasoner = new KAON2Reasoner(kb,imports);
785 // kaon2Reasoner.saveOntology(file, format);
786 throw new UnsupportedOperationException("Saving ontologies not yet implemented.");
787 }
788
789 public URL getReasonerURL() {
790 return reasonerURL;
791 }
792
793 /* (non-Javadoc)
794 * @see org.dllearner.core.Reasoner#getBaseURI()
795 */
796 public String getBaseURI() {
797 return null;
798 }
799
800 /* (non-Javadoc)
801 * @see org.dllearner.core.Reasoner#getPrefixes()
802 */
803 public Map<String, String> getPrefixes() {
804 return null;
805 }
806
807 // @Override
808 // public boolean hasDatatypeSupport() {
809 // return false;
810 // }
811
812 }