001/** 002 * Copyright (C) 2007-2009, 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 */ 020package org.dllearner.server; 021 022import org.apache.log4j.Logger; 023import org.dllearner.core.*; 024import org.dllearner.core.config.ConfigOption; 025import org.dllearner.kb.OWLFile; 026import org.dllearner.kb.sparql.*; 027import org.dllearner.learningproblems.PosNegLP; 028import org.dllearner.learningproblems.PosOnlyLP; 029import org.dllearner.parser.KBParser; 030import org.dllearner.parser.ParseException; 031import org.dllearner.utilities.datastructures.StringTuple; 032import org.dllearner.utilities.examples.AutomaticNegativeExampleFinderSPARQL; 033import org.dllearner.utilities.owl.OWLAPIRenderers; 034import org.dllearner.utilities.owl.OWLClassExpressionUtils; 035import org.semanticweb.owlapi.model.*; 036import uk.ac.manchester.cs.owl.owlapi.OWLClassImpl; 037import uk.ac.manchester.cs.owl.owlapi.OWLNamedIndividualImpl; 038import uk.ac.manchester.cs.owl.owlapi.OWLObjectPropertyImpl; 039 040import javax.jws.WebMethod; 041import javax.jws.WebService; 042import javax.jws.soap.SOAPBinding; 043import java.lang.reflect.Field; 044import java.lang.reflect.InvocationTargetException; 045import java.net.MalformedURLException; 046import java.net.URL; 047import java.util.*; 048 049/** 050 * DL-Learner web service interface. The web service makes use of the component 051 * architecture of DL-Learner (see 052 * <a href="http://dl-learner.org/wiki/Architecture">architecture wiki page</a>), 053 * i.e. it allows to create, configure and run components. In addition, it provides 054 * access to some reasoning and querying methods. 055 * 056 * @author Jens Lehmann 057 * 058 */ 059@WebService(name = "DLLearnerWebService") 060@SOAPBinding(style = SOAPBinding.Style.RPC) 061public class DLLearnerWS { 062 063 private static Logger logger = Logger.getLogger(DLLearnerWS.class); 064 065 private Map<Integer, ClientState> clients = new TreeMap<>(); 066 private Random rand=new Random(); 067 private static AnnComponentManager cm = AnnComponentManager.getInstance(); 068 069 /** 070 * Conversion between different data structures. 071 * 072 * @author Jens Lehmann 073 * @author Sebastian Hellmann 074 * 075 */ 076 public static class Datastructures { 077 078 public static boolean strToBool(String str) { 079 switch (str) { 080 case "true": 081 return true; 082 case "false": 083 return false; 084 default: 085 throw new Error("Cannot convert to boolean."); 086 } 087 } 088 089 /** 090 * easy conversion 091 * 092 * @param s 093 */ 094 public static String[] setToArray(Set<String> s) { 095 if(s==null)return null; 096 String[] ret=new String[s.size()]; 097 int i=0; 098 for (String value : s) { 099 ret[i] = value; 100 i++; 101 102 } 103 return ret; 104 105 } 106 107 public static String[] sortedSet2StringListIndividuals(Set<OWLIndividual> individuals){ 108 109 String[] ret=new String[individuals.size()]; 110 Iterator<OWLIndividual> i=individuals.iterator(); 111 int a=0; 112 while (i.hasNext()){ 113 ret[a++]=i.next().toStringID(); 114 } 115 Arrays.sort(ret); 116 return ret; 117 } 118 119 public static String[] sortedSet2StringListRoles(Set<OWLObjectProperty> s){ 120 121 String[] ret=new String[s.size()]; 122 Iterator<OWLObjectProperty> i=s.iterator(); 123 int a=0; 124 while (i.hasNext()){ 125 ret[a++]=i.next().toStringID(); 126 } 127 Arrays.sort(ret); 128 return ret; 129 } 130 131 public static String[] sortedSet2StringListConcepts(Set<OWLClass> s){ 132 133 String[] ret=new String[s.size()]; 134 Iterator<OWLClass> i=s.iterator(); 135 int a=0; 136 while (i.hasNext()){ 137 ret[a++]=i.next().toStringID(); 138 } 139 Arrays.sort(ret); 140 return ret; 141 } 142 143 } 144// /** 145// * Returns the DL-Learner version this web service is based on. 146// * @return DL-Learner-Build. 147// */ 148// @WebMethod 149// public String getBuild() { 150// return Info.build; 151// } 152 153 /** 154 * Method to check whether web service is online and how fast it responses. 155 * This method simply returns true. 156 * @return Always returns true. 157 */ 158 @WebMethod 159 public boolean ping() { 160 return true; 161 } 162 163 /** 164 * Generates a unique ID for the client and initialises a session. 165 * Using the ID the client can call the other web service methods. 166 * Two calls to this method are guaranteed to return different results. 167 * 168 * @return A session ID. 169 */ 170 @WebMethod 171 public int generateID() { 172 int id; 173 do { 174 id = Math.abs(rand.nextInt()); 175 } while(clients.containsKey(id)); 176 clients.put(id, new ClientState()); 177 logger.info("New client " + id + " at DL-Learner web service."); 178 return id; 179 } 180 181 /////////////////////////////////////// 182 // methods for basic component setup // 183 /////////////////////////////////////// 184 185 /** 186 * Gets a list of all DL-Learner components accessible via this web service. 187 * @return All components accessible via this web service. 188 */ 189 @WebMethod 190 public String[] getComponents() { 191 Set<String> components = cm.getComponentStrings(); 192 return components.toArray(new String[components.size()]); 193 } 194 195 /** 196 * Gets a list of all DL-Learner knowledge source components accessible via this web service. 197 * @return All knowledge source components accessible via this web service. 198 */ 199 @WebMethod 200 public String[] getKnowledgeSources() { 201 Set<String> knowledgeSources = cm.getComponentStringsOfType(KnowledgeSource.class); 202 return knowledgeSources.toArray(new String[knowledgeSources.size()]); 203 } 204 205 /** 206 * Gets a list of all DL-Learner reasoner components accessible via this web service. 207 * @return All reasoner components accessible via this web service. 208 */ 209 @WebMethod 210 public String[] getReasoners() { 211 Set<String> reasoners = cm.getComponentStringsOfType(AbstractReasonerComponent.class); 212 return reasoners.toArray(new String[reasoners.size()]); 213 } 214 215 /** 216 * Gets a list of all DL-Learner learning problem components accessible via this web service. 217 * @return All learning problem components accessible via this web service. 218 */ 219 @WebMethod 220 public String[] getLearningProblems() { 221 Set<String> learningProblems = cm.getComponentStringsOfType(AbstractLearningProblem.class); 222 return learningProblems.toArray(new String[learningProblems.size()]); 223 } 224 225 /** 226 * Gets a list of all DL-Learner learning algorithm components accessible via this web service. 227 * @return All learning algorithm components accessible via this web service. 228 */ 229 @WebMethod 230 public String[] getLearningAlgorithms() { 231 Set<String> learningAlgorithms = cm.getComponentStringsOfType(AbstractCELA.class); 232 return learningAlgorithms.toArray(new String[learningAlgorithms.size()]); 233 } 234 235 /** 236 * Gets the configuration options supported by the component. This allows e.g. to 237 * automatically build user interfaces for configuring components. 238 * @param component Name of the component. 239 * @param allInfo Whether or not complete information is desired (including option description, required, default value, example value). 240 * @return A list of configuration options supported by the component. 241 * @throws UnknownComponentException Thrown if component is not known (see {@link #getComponents()}). 242 */ 243 @WebMethod 244 public String[] getConfigOptions(String component, boolean allInfo) { 245 Class<? extends Component> componentClass = cm.getComponentClass(component); 246 Set<Field> options = AnnComponentManager.getConfigOptions(componentClass); 247 String[] optionsString = new String[options.size()]; 248 int i = 0; 249 for(Field f : options) { 250 ConfigOption option = f.getAnnotation(ConfigOption.class); 251 optionsString[i] = AnnComponentManager.getName(f); 252 if(allInfo) { 253 optionsString[i] += "#" + option.description(); 254 optionsString[i] += "#" + option.required(); 255 optionsString[i] += "#" + option.defaultValue(); 256 optionsString[i] += "#" + option.exampleValue(); 257 } 258 i++; 259 } 260 return optionsString; 261 } 262 263 /** 264 * Adds a knowledge source. 265 * 266 * @param id The session ID. 267 * @param component The name of the component. 268 * @param url The URL of the knowledge source. 269 * @return An identifier for the component. 270 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 271 * @throws UnknownComponentException Thrown if component is not known (see {@link #getComponents()}). 272 * @throws MalformedURLException Thrown if passed URL is malformed. 273 */ 274 @WebMethod 275 public int addKnowledgeSource(int id, String component, String url) throws ClientNotKnownException, UnknownComponentException, MalformedURLException { 276 logger.info("Adding knowledge source " + component + " with URL parameter " + url + "..."); 277 ClientState state = getState(id); 278 Class<? extends AbstractKnowledgeSource> ksClass = (Class<? extends AbstractKnowledgeSource>) cm.getComponentClass(component); 279 if(ksClass == null) 280 throw new UnknownComponentException(component); 281 AbstractKnowledgeSource ks = null; 282 try { 283 ks = ksClass.getConstructor().newInstance(); 284 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException 285 | NoSuchMethodException | SecurityException e) { 286 e.printStackTrace(); 287 } 288 if(ks instanceof OWLFile) { 289 ((OWLFile) ks).setUrl(new URL(url)); 290 } 291 logger.info("...done."); 292 return state.addKnowledgeSource(ks); 293 } 294 295 /** 296 * Removes a knowledge source. 297 * 298 * @param id The session ID. 299 * @param componentID ID of knowledge source to remove. 300 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 301 */ 302 @WebMethod 303 public void removeKnowledgeSource(int id, int componentID) throws ClientNotKnownException { 304 getState(id).removeKnowledgeSource(componentID); 305 } 306 307 /** 308 * Sets the reasoner to use. 309 * 310 * @param id The session ID. 311 * @param component The name of the component. 312 * @return An identifier for the component. 313 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 314 * @throws UnknownComponentException Thrown if component is not known (see {@link #getComponents()}). 315 */ 316 @WebMethod 317 public int setReasoner(int id, String component) throws ClientNotKnownException, UnknownComponentException { 318 logger.info("Setting reasoner " + component + "..."); 319 ClientState state = getState(id); 320 Class<? extends AbstractReasonerComponent> rcClass = (Class<? extends AbstractReasonerComponent>) cm.getComponentClass(component); 321 if(rcClass == null) 322 throw new UnknownComponentException(component); 323 324 AbstractReasonerComponent rc = null; 325 try { 326 rc = rcClass.getConstructor(Set.class).newInstance(state.getKnowledgeSources()); 327 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException 328 | NoSuchMethodException | SecurityException e) { 329 e.printStackTrace(); 330 } 331 logger.info("...done."); 332 return state.setReasonerComponent(rc); 333 } 334 335 /** 336 * Sets the learning problem to use. 337 * 338 * @param id The session ID. 339 * @param component The name of the component. 340 * @return An identifier for the component. 341 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 342 * @throws UnknownComponentException Thrown if component is not known (see {@link #getComponents()}). 343 */ 344 @WebMethod 345 public int setLearningProblem(int id, String component) throws ClientNotKnownException, UnknownComponentException { 346 logger.info("Setting learning problem " + component + "..."); 347 ClientState state = getState(id); 348 Class<? extends AbstractClassExpressionLearningProblem> lpClass = (Class<? extends AbstractClassExpressionLearningProblem>) cm.getComponentClass(component); 349 if(lpClass == null) 350 throw new UnknownComponentException(component); 351 352 AbstractClassExpressionLearningProblem lp = null; 353 try { 354 lp = lpClass.getConstructor(AbstractReasonerComponent.class).newInstance(state.getReasonerComponent()); 355 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException 356 | NoSuchMethodException | SecurityException e) { 357 e.printStackTrace(); 358 } 359 logger.info("...done."); 360 return state.setLearningProblem(lp); 361 } 362 363 /** 364 * Sets the learning algorithm to use. 365 * 366 * @param id The session ID. 367 * @param component The name of the component. 368 * @return An identifier for the component. 369 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 370 * @throws UnknownComponentException Thrown if component is not known (see {@link #getComponents()}). 371 * @throws LearningProblemUnsupportedException Thrown if the learning problem is not supported by the specified learning algorithm. 372 */ 373 @WebMethod 374 public int setLearningAlgorithm(int id, String component) throws ClientNotKnownException, UnknownComponentException { 375 logger.info("Setting learning algorithm " + component + "..."); 376 ClientState state = getState(id); 377 Class<? extends AbstractCELA> laClass = (Class<? extends AbstractCELA>) cm.getComponentClass(component); 378 if(laClass == null) 379 throw new UnknownComponentException(component); 380 381 AbstractCELA la = null; 382 try { 383 la = laClass.getConstructor(AbstractClassExpressionLearningProblem.class, AbstractReasonerComponent.class) 384 .newInstance(state.getLearningProblem(), state.getReasonerComponent()); 385 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException 386 | NoSuchMethodException | SecurityException e) { 387 e.printStackTrace(); 388 } 389 logger.info("...done."); 390 return state.setLearningAlgorithm(la); 391 } 392 393 /** 394 * Initialise all components. 395 * @param id Session ID. 396 * @throws ComponentInitException Thrown if an error occurs during component initialisation. 397 */ 398 @WebMethod 399 public void initAll(int id) throws ClientNotKnownException, ComponentInitException { 400 ClientState state = getState(id); 401 logger.info("Initializing knowledge sources..."); 402 for(AbstractKnowledgeSource ks : state.getKnowledgeSources()) 403 ks.init(); 404 logger.info("Initializing reasoner..."); 405 state.getReasonerComponent().init(); 406 logger.info("Initializing learning problem..."); 407 state.getLearningProblem().init(); 408 logger.info("Initializing learning algorithm..."); 409 state.getLearningAlgorithm().init(); 410 } 411 412 /** 413 * Initialise the specified component. 414 * @param id Session-ID. 415 * @param componentID Component-ID. 416 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 417 * @throws UnknownComponentException Thrown if the component is unknown. 418 * @throws ComponentInitException 419 */ 420 @WebMethod 421 public void init(int id, int componentID) throws ClientNotKnownException, ComponentInitException { 422 ClientState state = getState(id); 423 AbstractComponent component = state.getComponent(componentID); 424 component.init(); 425 } 426 427 /** 428 * Starts the learning algorithm and returns the best concept found. This 429 * method will block until learning is completed. 430 * 431 * @param id Session ID. 432 * @param format The format of the result string: "manchester", "kb", "dl". 433 * @return The best solution found. 434 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 435 */ 436 @WebMethod 437 public String learn(int id, String format) throws ClientNotKnownException { 438 ClientState state = getState(id); 439 state.getLearningAlgorithm().start(); 440 OWLClassExpression solution = state.getLearningAlgorithm().getCurrentlyBestDescription(); 441 switch (format) { 442 case "manchester": 443 return OWLAPIRenderers.toManchesterOWLSyntax(solution); 444 case "kb": 445 return OWLAPIRenderers.toManchesterOWLSyntax(solution); 446 default: 447 return solution.toString(); 448 } 449 } 450 451 /** 452 * Returns a list of JSON encoded description including extra information 453 * (which partially depends on the learning problem) such as the accuracy 454 * of the learned description. 455 * 456 * @param id The session ID. 457 * @return A JSON string encoding learned descriptions. 458 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 459 */ 460 @WebMethod 461 public String learnDescriptionsEvaluated(int id) throws ClientNotKnownException { 462 ClientState state = getState(id); 463 state.getLearningAlgorithm().start(); 464 NavigableSet<? extends EvaluatedDescription> descriptions = state.getLearningAlgorithm() 465 .getCurrentlyBestEvaluatedDescriptions(); 466 String json = "{"; 467 int count = 1; 468 for (EvaluatedDescription description : descriptions.descendingSet()) { 469 if (count > 1) 470 json += ",\"solution" + count + "\" : " + description.asJSON(); 471 else 472 json += "\"solution" + count + "\" : " + description.asJSON(); 473 count++; 474 } 475 json += "}"; 476 return json; 477 } 478 479 /** 480 * Returns a list of JSON encoded description including extra information 481 * (which partially depends on the learning problem) such as the accuracy 482 * of the learned description. 483 * 484 * @param id The session ID. 485 * @param limit Maximum number of results desired. 486 * @return A JSON string encoding learned descriptions. 487 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 488 */ 489 @WebMethod 490 public String learnDescriptionsEvaluatedLimit(int id, int limit) throws ClientNotKnownException { 491 ClientState state = getState(id); 492 state.getLearningAlgorithm().start(); 493 List<? extends EvaluatedDescription> descriptions = state.getLearningAlgorithm().getCurrentlyBestEvaluatedDescriptions(limit); 494 String json = "{"; 495 int count = 1; 496 for(EvaluatedDescription description : descriptions) { 497 if (count>1) json += ",\"solution" + count + "\" : " + description.asJSON(); 498 else json += "\"solution" + count + "\" : " + description.asJSON(); 499 count++; 500 } 501 json+="}"; 502 return json; 503 } 504 505 /** 506 * Starts the learning algorithm and returns immediately. The learning 507 * algorithm is executed in its own thread and can be queried and 508 * controlled using other Web Service methods. 509 * 510 * @param id Session ID. 511 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 512 */ 513 @WebMethod 514 public void learnThreaded(int id) throws ClientNotKnownException { 515 final ClientState state = getState(id); 516 Thread learningThread = new Thread() { 517 @Override 518 public void run() { 519// state.setAlgorithmRunning(true); 520 state.getLearningAlgorithm().start(); 521// state.setAlgorithmRunning(false); 522 } 523 }; 524 learningThread.start(); 525 } 526 527 /** 528 * 529 * @param id The session ID. 530 * @return 531 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 532 */ 533 @WebMethod 534 public String getCurrentlyBestConcept(int id) throws ClientNotKnownException { 535 ClientState state = getState(id); 536 return state.getLearningAlgorithm().getCurrentlyBestEvaluatedDescription().toString(); 537 } 538 539 /** 540 * 541 * @param id The session ID. 542 * @param nrOfConcepts 543 * @param format 544 * @return 545 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 546 */ 547 @WebMethod 548 public String[] getCurrentlyBestConcepts(int id, int nrOfConcepts, String format) throws ClientNotKnownException { 549 ClientState state = getState(id); 550 List<OWLClassExpression> bestConcepts = state.getLearningAlgorithm().getCurrentlyBestDescriptions(nrOfConcepts); 551 List<String> conc= new LinkedList<>(); 552 Iterator<OWLClassExpression> iter=bestConcepts.iterator(); 553 while (iter.hasNext()) 554 switch (format) { 555 case "manchester": 556 conc.add(OWLAPIRenderers.toManchesterOWLSyntax(iter.next())); 557 break; 558 case "kb": 559 conc.add(OWLAPIRenderers.toManchesterOWLSyntax(iter.next())); 560 break; 561 default: 562 conc.add(iter.next().toString()); 563 break; 564 } 565 return conc.toArray(new String[conc.size()]); 566 } 567 568 /** 569 * 570 * @param id The session ID. 571 * @param limit 572 * @return 573 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 574 */ 575 @WebMethod 576 public String getCurrentlyBestEvaluatedDescriptions(int id, int limit) throws ClientNotKnownException{ 577 return currentlyBestEvaluatedDescriptions(id,limit,-1,false); 578 } 579 580 /** 581 * 582 * @param id The session ID. 583 * @param nrOfDescriptions 584 * @param accuracyThreshold 585 * @param filterNonMinimalDescriptions 586 * @return 587 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 588 */ 589 @WebMethod 590 public String getCurrentlyBestEvaluatedDescriptionsFiltered(int id,int nrOfDescriptions, double accuracyThreshold, boolean filterNonMinimalDescriptions) throws ClientNotKnownException 591 { 592 return currentlyBestEvaluatedDescriptions(id,nrOfDescriptions,accuracyThreshold,filterNonMinimalDescriptions); 593 } 594 595 /** 596 * 597 * @param id The session ID. 598 * @param nrOfDescriptions 599 * @param accuracyThreshold 600 * @param filterNonMinimalDescriptions 601 * @return 602 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 603 */ 604 private String currentlyBestEvaluatedDescriptions(int id, int nrOfDescriptions, double accuracyThreshold, 605 boolean filterNonMinimalDescriptions) throws ClientNotKnownException { 606 ClientState state = getState(id); 607 List<? extends EvaluatedDescription> descriptions; 608 if (accuracyThreshold != -1) { 609 descriptions = state.getLearningAlgorithm().getCurrentlyBestEvaluatedDescriptions(nrOfDescriptions, 610 accuracyThreshold, filterNonMinimalDescriptions); 611 } else { 612 descriptions = state.getLearningAlgorithm().getCurrentlyBestEvaluatedDescriptions(nrOfDescriptions); 613 } 614 String json = "{"; 615 System.out.println(json); 616 int count = 1; 617 for (EvaluatedDescription description : descriptions) { 618 if (count > 1) 619 json += ",\"solution" + count + "\" : " + description.asJSON(); 620 else 621 json += "\"solution" + count + "\" : " + description.asJSON(); 622 count++; 623 } 624 json += "}"; 625 return json; 626 } 627 628 /** 629 * 630 * @param id The session ID. 631 * @return 632 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 633 */ 634 @WebMethod 635 public boolean isAlgorithmRunning(int id) throws ClientNotKnownException { 636 return getState(id).getLearningAlgorithm().isRunning(); 637 } 638 639 /** 640 * Stops the learning algorithm smoothly. 641 * @param id The session ID. 642 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 643 */ 644 @WebMethod 645 public void stop(int id) throws ClientNotKnownException { 646 getState(id).getLearningAlgorithm().stop(); 647 } 648 649 ///////////////////////////////////////// 650 // methods for component configuration // 651 ///////////////////////////////////////// 652 653 /** 654 * 655 * @param id The session ID. 656 * @param positiveExamples 657 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 658 */ 659 @WebMethod 660 public void setPositiveExamples(int id, String[] positiveExamples) throws ClientNotKnownException { 661 ClientState state = getState(id); 662 Set<String> posExamples = new TreeSet<>(Arrays.asList(positiveExamples)); 663 SortedSet<OWLIndividual> inds = new TreeSet<>(); 664 for (String ex : posExamples) { 665 inds.add(new OWLNamedIndividualImpl(IRI.create(ex))); 666 } 667 if (state.getLearningProblem() instanceof PosOnlyLP) { 668 ((PosOnlyLP)state.getLearningProblem()).setPositiveExamples(inds); 669 } else { 670 ((PosNegLP)state.getLearningProblem()).setPositiveExamples(inds); 671 } 672 } 673 674 /** 675 * 676 * @param id The session ID. 677 * @param negativeExamples 678 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 679 */ 680 @WebMethod 681 public void setNegativeExamples(int id, String[] negativeExamples) throws ClientNotKnownException { 682 ClientState state = getState(id); 683 Set<String> negExamples = new TreeSet<>(Arrays.asList(negativeExamples)); 684 Set<OWLIndividual> inds = new HashSet<>(); 685 for (String ex : negExamples) { 686 inds.add(new OWLNamedIndividualImpl(IRI.create(ex))); 687 } 688 ((PosNegLP)state.getLearningProblem()).setNegativeExamples(inds); 689 } 690 691 /** 692 * 693 * @param sessionID The session ID. 694 * @param componentID The componentID. 695 * @param optionName The name of the configuration option. 696 * @param value 697 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 698 * @throws UnknownComponentException 699 */ 700 @WebMethod 701 public void applyConfigEntryInt(int sessionID, int componentID, String optionName, Integer value) throws ClientNotKnownException, UnknownComponentException { 702 applyConfigEntry(sessionID, componentID,optionName,value); 703 } 704 705 /** 706 * 707 * @param sessionID The session ID. 708 * @param componentID The componentID. 709 * @param optionName The name of the configuration option. 710 * @param value 711 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 712 * @throws UnknownComponentException 713 */ 714 @WebMethod 715 public void applyConfigEntryString(int sessionID, int componentID, String optionName, String value) throws ClientNotKnownException, UnknownComponentException { 716 applyConfigEntry(sessionID, componentID,optionName,value); 717 } 718 719 /** 720 * 721 * @param sessionID The session ID. 722 * @param componentID The componentID. 723 * @param optionName The name of the configuration option. 724 * @param value 725 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 726 * @throws UnknownComponentException 727 * @throws MalformedURLException 728 */ 729 @WebMethod 730 public void applyConfigEntryURL(int sessionID, int componentID, String optionName, String value) throws ClientNotKnownException, UnknownComponentException, MalformedURLException { 731 // URLs are passed as String and then converted 732 URL url = new URL(value); 733 applyConfigEntry(sessionID, componentID,optionName,url); 734 } 735 736 /** 737 * 738 * @param sessionID The session ID. 739 * @param componentID The componentID. 740 * @param optionName The name of the configuration option. 741 * @param value 742 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 743 * @throws UnknownComponentException 744 */ 745 @WebMethod 746 public void applyConfigEntryStringArray(int sessionID, int componentID, String optionName, String[] value) throws ClientNotKnownException, UnknownComponentException { 747 Set<String> stringSet = new TreeSet<>(Arrays.asList(value)); 748 applyConfigEntry(sessionID, componentID,optionName,stringSet); 749 } 750 751 /** 752 * 753 * @param sessionID The session ID. 754 * @param componentID The componentID. 755 * @param optionName The name of the configuration option. 756 * @param keys 757 * @param values 758 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 759 * @throws UnknownComponentException 760 */ 761 @WebMethod 762 public void applyConfigEntryStringTupleList(int sessionID, int componentID, String optionName, String[] keys, String[] values) throws ClientNotKnownException, UnknownComponentException { 763 List<StringTuple> tuples = new LinkedList<>(); 764 for(int i=0; i<keys.length; i++) { 765 StringTuple st = new StringTuple(keys[i],values[i]); 766 tuples.add(st); 767 } 768// Set<String> stringSet = new TreeSet<String>(Arrays.asList(value)); 769 applyConfigEntry(sessionID, componentID, optionName, tuples); 770 } 771 772 /** 773 * 774 * @param sessionID The session ID. 775 * @param componentID The componentID. 776 * @param optionName The name of the configuration option. 777 * @param value 778 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 779 * @throws UnknownComponentException 780 */ 781 @WebMethod 782 public void applyConfigEntryBoolean(int sessionID, int componentID, String optionName, Boolean value) throws ClientNotKnownException, UnknownComponentException { 783 applyConfigEntry(sessionID, componentID,optionName,value); 784 } 785 786 /** 787 * 788 * @param sessionID The session ID. 789 * @param componentID The componentID. 790 * @param optionName The name of the configuration option. 791 * @param value 792 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 793 * @throws UnknownComponentException 794 */ 795 private void applyConfigEntry(int sessionID, int componentID, String optionName, Object value) throws ClientNotKnownException { 796 ClientState state = getState(sessionID); 797 AbstractComponent component = state.getComponent(componentID); 798 System.out.println("Config option->" + component + "::" + optionName + "=" + value); 799 try { 800 Field field = component.getClass().getDeclaredField(optionName); 801 field.setAccessible(true); 802 if(optionName.equals("classToDescribe")) { 803 value = new OWLClassImpl(IRI.create((URL)value)); 804 } else if(optionName.equals("ignoredConcepts")) { 805 Set<OWLClass> ignoredConcepts = new HashSet<>(); 806 for (String iri : (TreeSet<String>)value) { 807 ignoredConcepts.add(new OWLClassImpl(IRI.create(iri))); 808 } 809 value = ignoredConcepts; 810 } 811 field.set(component, value); 812 } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) { 813 e.printStackTrace(); 814 } 815// try { 816// component.getClass().getMethod(optionName, value.getClass()).invoke(component, value); 817// } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException 818// | SecurityException e) { 819// e.printStackTrace(); 820// } 821// cm.applyConfigEntry(component, optionName, value); 822 } 823 824 /** 825 * 826 * @param sessionID The session ID. 827 * @param componentID The componentID. 828 * @param optionName The name of the configuration option. 829 * @return 830 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 831 * @throws UnknownComponentException 832 * @throws ConfigOptionTypeException 833 */ 834 @WebMethod 835 public String[] getConfigOptionValueStringArray(int sessionID, int componentID, String optionName) throws ClientNotKnownException, UnknownComponentException, ConfigOptionTypeException { 836 return getConfigOptionValue(sessionID, componentID, optionName, String[].class); 837 } 838 839 /** 840 * 841 * @param sessionID The session ID. 842 * @param componentID The componentID. 843 * @param optionName The name of the configuration option. 844 * @return 845 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 846 * @throws UnknownComponentException 847 * @throws ConfigOptionTypeException 848 */ 849 @WebMethod 850 public String getConfigOptionValueString(int sessionID, int componentID, String optionName) throws ClientNotKnownException, UnknownComponentException, ConfigOptionTypeException { 851 return getConfigOptionValue(sessionID, componentID, optionName, String.class); 852 } 853 854 /** 855 * 856 * @param sessionID The session ID. 857 * @param componentID The componentID. 858 * @param optionName The name of the configuration option. 859 * @return 860 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 861 * @throws UnknownComponentException 862 * @throws ConfigOptionTypeException 863 */ 864 @WebMethod 865 public String getConfigOptionValueURL(int sessionID, int componentID, String optionName) throws ClientNotKnownException, UnknownComponentException, ConfigOptionTypeException { 866 URL url = getConfigOptionValue(sessionID, componentID, optionName, URL.class); 867 return url.toString(); 868 } 869 870 /** 871 * 872 * @param sessionID The session ID. 873 * @param componentID The componentID. 874 * @param optionName The name of the configuration option. 875 * @return 876 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 877 * @throws UnknownComponentException 878 * @throws ConfigOptionTypeException 879 */ 880 @WebMethod 881 public Double getConfigOptionValueDouble(int sessionID, int componentID, String optionName) throws ClientNotKnownException, UnknownComponentException, ConfigOptionTypeException { 882 return getConfigOptionValue(sessionID, componentID, optionName, Double.class); 883 } 884 885 /** 886 * 887 * @param sessionID The session ID. 888 * @param componentID The componentID. 889 * @param optionName The name of the configuration option. 890 * @return 891 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 892 * @throws UnknownComponentException 893 * @throws ConfigOptionTypeException 894 */ 895 @WebMethod 896 public Boolean getConfigOptionValueBoolean(int sessionID, int componentID, String optionName) throws ClientNotKnownException, UnknownComponentException, ConfigOptionTypeException { 897 return getConfigOptionValue(sessionID, componentID, optionName, Boolean.class); 898 } 899 900 /** 901 * 902 * @param sessionID The session ID. 903 * @param componentID The componentID. 904 * @param optionName The name of the configuration option. 905 * @return 906 * @throws ClientNotKnownException Thrown if client (session ID) is not known. 907 * @throws UnknownComponentException 908 * @throws ConfigOptionTypeException 909 */ 910 @WebMethod 911 public Integer getConfigOptionValueInt(int sessionID, int componentID, String optionName) throws ClientNotKnownException, UnknownComponentException, ConfigOptionTypeException { 912 return getConfigOptionValue(sessionID, componentID, optionName, Integer.class); 913 } 914 915 //////////////////////////////////// 916 // reasoning and querying methods // 917 //////////////////////////////////// 918 919 @WebMethod 920 public String[] getAtomicConcepts(int id) throws ClientNotKnownException { 921 Set<OWLClass> atomicConcepts = getState(id).getReasonerComponent().getClasses(); 922 return Datastructures.sortedSet2StringListConcepts(atomicConcepts); 923 } 924 925 @WebMethod 926 public String getSubsumptionHierarchy(int id) throws ClientNotKnownException { 927 return getState(id).getReasonerComponent().toString(); 928 } 929 930 @WebMethod 931 public String[] retrieval(int id, String conceptString) throws ClientNotKnownException, ParseException { 932 ClientState state = getState(id); 933 // call parser to parse concept 934 OWLClassExpression concept = KBParser.parseConcept(conceptString); 935 Set<OWLIndividual> individuals = state.getReasonerComponent().getIndividuals(concept); 936 return Datastructures.sortedSet2StringListIndividuals(individuals); 937 } 938 939 @WebMethod 940 public int getConceptLength(String conceptString) throws ParseException { 941 // call parser to parse concept 942 return OWLClassExpressionUtils.getLength(KBParser.parseConcept(conceptString)); 943 } 944 945 @WebMethod 946 public String[] getAtomicRoles(int id) throws ClientNotKnownException { 947 ClientState state = getState(id); 948 Set<OWLObjectProperty> roles = state.getReasonerComponent().getObjectProperties(); 949 return Datastructures.sortedSet2StringListRoles(roles); 950 } 951 952 @WebMethod 953 public String[] getInstances(int id) throws ClientNotKnownException { 954 ClientState state = getState(id); 955 Set<OWLIndividual> individuals = state.getReasonerComponent().getIndividuals(); 956 return Datastructures.sortedSet2StringListIndividuals(individuals); 957 } 958 959 @WebMethod 960 public String[] getIndividualsForARole(int id, String role) throws ClientNotKnownException { 961 ClientState state = getState(id); 962 Map<OWLIndividual,SortedSet<OWLIndividual>> m = state.getReasonerComponent().getPropertyMembers( 963 new OWLObjectPropertyImpl(IRI.create(role))); 964 Set<OWLIndividual> individuals = m.keySet(); 965 return Datastructures.sortedSet2StringListIndividuals(individuals); 966 } 967 968 //////////////////////////////////////// 969 // SPARQL component methods // 970 //////////////////////////////////////// 971 972 @WebMethod 973 public String getAsJSON(int sessionID, int queryID) throws ClientNotKnownException, SparqlQueryException 974 { 975 ClientState state = getState(sessionID); 976 //ResultSet resultSet=null; 977 String json = null; 978 try { 979 json = state.getQuery(queryID).getJson(); 980 }catch (Exception e) { 981 e.printStackTrace(); 982 throw new SparqlQueryException("SparqlQuery failed"+e.toString()); 983 } 984 985 if(json == null) { throw new SparqlQueryException("Sparql Query failed. Please try again later.");} 986 return json; 987 //if ((json=state.getQuery(queryID).getJson())!=null) return json; 988 //else if ((resultSet=state.getQuery(queryID).getResultSet())!=null) return SparqlQuery.getAsJSON(resultSet); 989 //else return SparqlQuery.getAsJSON(state.getQuery(queryID).send()); 990 } 991 992 @WebMethod 993 public String getAsXMLString(int sessionID, int queryID) throws ClientNotKnownException, SparqlQueryException 994 { 995 ClientState state = getState(sessionID); 996 997 String xml = null; 998 try{ 999 xml = state.getQuery(queryID).getXMLString(); 1000 }catch (Exception e) { 1001 e.printStackTrace(); 1002 throw new SparqlQueryException("SparqlQuery failed"+e.toString()); 1003 } 1004 1005 if(xml == null) throw new SparqlQueryException("SparqlQuery failed xml was null"); 1006 return xml; 1007 //if ((resultSet=state.getQuery(queryID).getResultSet())!=null) return SparqlQuery.getAsXMLString(resultSet); 1008 //if ((json=state.getQuery(queryID).getJson())!=null) return SparqlQuery.getAsXMLString(SparqlQuery.JSONtoResultSet(json)); 1009 //else return SparqlQuery.getAsXMLString(state.getQuery(queryID).send()); 1010 } 1011 1012 @WebMethod 1013 public int sparqlQueryThreaded(int sessionID, int componentID, String query) throws ClientNotKnownException 1014 { 1015 final ClientState state = getState(sessionID); 1016 AbstractComponent component = state.getComponent(componentID); 1017 final SparqlKnowledgeSource ks=(SparqlKnowledgeSource)component; 1018 final int id=state.addQuery(ks.sparqlQuery(query)); 1019 Thread sparqlThread = new Thread() { 1020 @Override 1021 public void run() { 1022 if (ks.isUseCache()){ 1023 Cache cache=new Cache(ks.getCacheDir()); 1024 cache.executeSparqlQuery(state.getQuery(id)); 1025 } 1026 else{ 1027 state.getQuery(id).send(); 1028 } 1029 } 1030 }; 1031 sparqlThread.start(); 1032 return id; 1033 } 1034 1035 @WebMethod 1036 public String sparqlQuery(int sessionID, int componentID, String query) throws ClientNotKnownException 1037 { 1038 ClientState state = getState(sessionID); 1039 AbstractComponent component = state.getComponent(componentID); 1040 SparqlKnowledgeSource ks=(SparqlKnowledgeSource)component; 1041 return ks.getSPARQLTasks().query(query); 1042 /*SparqlQuery sparql=ks.sparqlQuery(query); 1043 if (ks.isUseCache()){ 1044 Cache cache=new Cache(ks.getCacheDir()); 1045 return cache.executeSparqlQuery(sparql); 1046 } 1047 else return sparql.getJson();*/ 1048 } 1049 1050 /** 1051 * Queries one of the standard endpoints defined in DL-Learner. 1052 * @param predefinedEndpoint A string describing the endpoint e.g. DBpedia. 1053 * @param query The SPARQL query. 1054 * @param useCache Specify whether to use a cache for queries. 1055 * @return The result of the SPARQL query in JSON format or null if the endpoint does not exist. 1056 * @see SparqlEndpoint#getEndpointByName(String) 1057 */ 1058 @WebMethod 1059 public String sparqlQueryPredefinedEndpoint(String predefinedEndpoint, String query, boolean useCache) { 1060 SparqlEndpoint endpoint = SparqlEndpoint.getEndpointByName(predefinedEndpoint); 1061 SPARQLTasks st; 1062 if(useCache) { 1063 st = new SPARQLTasks(endpoint); 1064 } else { 1065 st = new SPARQLTasks(Cache.getDefaultCache(), endpoint); 1066 } 1067 return st.query(query); 1068 } 1069 1070 @WebMethod 1071 public boolean isSparqlQueryRunning(int sessionID, int queryID) throws ClientNotKnownException 1072 { 1073 ClientState state = getState(sessionID); 1074 return state.getQuery(queryID).isRunning(); 1075 } 1076 1077 @WebMethod 1078 public void stopSparqlThread(int sessionID, int queryID) throws ClientNotKnownException 1079 { 1080 ClientState state = getState(sessionID); 1081 state.getQuery(queryID).stop(); 1082 } 1083 1084 @WebMethod 1085 public int[] getConceptDepth(int id, int nrOfConcepts) throws ClientNotKnownException { 1086 ClientState state = getState(id); 1087 List<OWLClassExpression> bestConcepts = state.getLearningAlgorithm().getCurrentlyBestDescriptions(nrOfConcepts); 1088 Iterator<OWLClassExpression> iter = bestConcepts.iterator(); 1089 int[] depth = new int[bestConcepts.size()]; 1090 int i = 0; 1091 while (iter.hasNext()) { 1092 depth[i] = OWLClassExpressionUtils.getDepth(iter.next()); 1093 i++; 1094 } 1095 return depth; 1096 } 1097 1098 @WebMethod 1099 public int[] getConceptArity(int id, int nrOfConcepts) throws ClientNotKnownException { 1100 ClientState state = getState(id); 1101 List<OWLClassExpression> bestConcepts = state.getLearningAlgorithm().getCurrentlyBestDescriptions(nrOfConcepts); 1102 Iterator<OWLClassExpression> iter = bestConcepts.iterator(); 1103 int[] arity = new int[bestConcepts.size()]; 1104 int i = 0; 1105 while (iter.hasNext()) { 1106 arity[i] = OWLClassExpressionUtils.getArity(iter.next()); 1107 i++; 1108 } 1109 return arity; 1110 } 1111 1112 @WebMethod 1113 public String SparqlRetrieval(String conceptString,int limit) { 1114 // call parser to parse concept 1115// return SparqlQueryDescriptionConvertVisitor.getSparqlQuery(conceptString,limit, false, false); 1116 // TODO Refactoring replace 1117 return null; 1118 } 1119 1120 @WebMethod 1121 public String[] getNegativeExamples(int sessionID, int componentID,String[] positives, int results, String namespace, String[] filterClasses) throws ClientNotKnownException 1122 { 1123 int sparqlResultSetLimit = 500; 1124 SortedSet<String> positiveSet = new TreeSet<>(Arrays.asList(positives)); 1125 SortedSet<String> filterSet = new TreeSet<>(Arrays.asList(filterClasses)); 1126 ClientState state = getState(sessionID); 1127 AbstractComponent component = state.getComponent(componentID); 1128 SparqlKnowledgeSource ks=(SparqlKnowledgeSource)component; 1129 SPARQLTasks task=ks.getSPARQLTasks(); 1130 AutomaticNegativeExampleFinderSPARQL finder=new AutomaticNegativeExampleFinderSPARQL(positiveSet,task,filterSet); 1131 1132 /*finder.makeNegativeExamplesFromNearbyClasses(positiveSet, sparqlResultSetLimit); 1133 SortedSet<String> negExamples=finder.getNegativeExamples(results); 1134 if (negExamples.isEmpty()){*/ 1135 finder.makeNegativeExamplesFromParallelClasses(positiveSet, sparqlResultSetLimit); 1136 SortedSet<String> negExamples=finder.getNegativeExamples(results); 1137 if(negExamples.isEmpty()){ 1138 finder.makeNegativeExamplesFromRelatedInstances(positiveSet, namespace); 1139 negExamples = finder.getNegativeExamples(results); 1140 if(negExamples.isEmpty()){ 1141 finder.makeNegativeExamplesFromSuperClassesOfInstances(positiveSet, sparqlResultSetLimit); 1142 negExamples = finder.getNegativeExamples(results); 1143 if(negExamples.isEmpty()) { 1144 finder.makeNegativeExamplesFromRandomInstances(); 1145 negExamples = finder.getNegativeExamples(results); 1146 } 1147 } 1148 } 1149 //} 1150 1151 return negExamples.toArray(new String[negExamples.size()]); 1152 } 1153 1154 ///////////////////////////// 1155 // private utility methods // 1156 ///////////////////////////// 1157 1158 // returns session state or throws client not known exception 1159 private ClientState getState(int id) throws ClientNotKnownException { 1160 ClientState state = clients.get(id); 1161 if(state==null) 1162 throw new ClientNotKnownException(id); 1163 return state; 1164 } 1165 1166 @SuppressWarnings({"unchecked"}) 1167 private <T> T getConfigOptionValue(int sessionID, int componentID, String optionName, Class<T> clazz) throws ClientNotKnownException, UnknownComponentException, ConfigOptionTypeException { 1168 Object value = getConfigOptionValue(sessionID, componentID, optionName); 1169 if(clazz.isInstance(value)) 1170 return (T) value; 1171 else 1172 throw new ConfigOptionTypeException(optionName, clazz, value.getClass()); 1173 } 1174 1175 private Object getConfigOptionValue(int sessionID, int componentID, String optionName) throws ClientNotKnownException { 1176 ClientState state = getState(sessionID); 1177 AbstractComponent component = state.getComponent(componentID); 1178 return "";//cm.getConfigOptionValue(component, optionName); 1179 } 1180 1181}