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;
021
022 import java.io.BufferedReader;
023 import java.io.DataInputStream;
024 import java.io.IOException;
025 import java.io.InputStream;
026 import java.io.InputStreamReader;
027 import java.lang.annotation.Annotation;
028 import java.lang.reflect.Constructor;
029 import java.lang.reflect.InvocationTargetException;
030 import java.lang.reflect.Method;
031 import java.util.ArrayList;
032 import java.util.Arrays;
033 import java.util.Collection;
034 import java.util.Comparator;
035 import java.util.HashMap;
036 import java.util.HashSet;
037 import java.util.LinkedList;
038 import java.util.List;
039 import java.util.Map;
040 import java.util.Set;
041 import java.util.TreeMap;
042 import java.util.TreeSet;
043 import java.util.Map.Entry;
044
045 import org.apache.log4j.Logger;
046 import org.dllearner.algorithms.DisjointClassesLearner;
047 import org.dllearner.algorithms.SimpleSubclassLearner;
048 import org.dllearner.algorithms.celoe.CELOE;
049 import org.dllearner.algorithms.properties.DataPropertyDomainAxiomLearner;
050 import org.dllearner.algorithms.properties.DataPropertyRangeAxiomLearner;
051 import org.dllearner.algorithms.properties.DisjointDataPropertyAxiomLearner;
052 import org.dllearner.algorithms.properties.DisjointObjectPropertyAxiomLearner;
053 import org.dllearner.algorithms.properties.EquivalentDataPropertyAxiomLearner;
054 import org.dllearner.algorithms.properties.EquivalentObjectPropertyAxiomLearner;
055 import org.dllearner.algorithms.properties.FunctionalDataPropertyAxiomLearner;
056 import org.dllearner.algorithms.properties.FunctionalObjectPropertyAxiomLearner;
057 import org.dllearner.algorithms.properties.InverseFunctionalObjectPropertyAxiomLearner;
058 import org.dllearner.algorithms.properties.ObjectPropertyDomainAxiomLearner;
059 import org.dllearner.algorithms.properties.ObjectPropertyRangeAxiomLearner;
060 import org.dllearner.algorithms.properties.SubDataPropertyOfAxiomLearner;
061 import org.dllearner.algorithms.properties.SubObjectPropertyOfAxiomLearner;
062 import org.dllearner.algorithms.properties.SymmetricObjectPropertyAxiomLearner;
063 import org.dllearner.algorithms.properties.TransitiveObjectPropertyAxiomLearner;
064 import org.dllearner.core.options.ConfigEntry;
065 import org.dllearner.core.options.ConfigOption;
066 import org.dllearner.core.options.InvalidConfigOptionValueException;
067 import org.dllearner.utilities.datastructures.Maps;
068
069 /**
070 * Central manager class for DL-Learner. There are currently four types of
071 * components in DL-Learner: knowledge sources, reasoners, learning problems,
072 * and learning algorithms. For accessing these components you should create
073 * instances and configure them using this class. The component manager is
074 * implemented as a Singleton and will read the components file (containing a
075 * list of all components) at startup. This allows interfaces (command line,
076 * graphical, web service) to easily query the available components, set and get
077 * their configuration options, and run the algorithm.
078 *
079 * @author Jens Lehmann
080 *
081 */
082 public final class ComponentManager {
083
084 private static Logger logger = Logger
085 .getLogger(ComponentManager.class);
086
087 private ComponentPool pool = new ComponentPool();
088
089 // these variables are valid for the complete lifetime of a DL-Learner session
090 private static Collection<Class<? extends AbstractComponent>> components;
091 private static Collection<Class<? extends AbstractKnowledgeSource>> knowledgeSources;
092 private static Collection<Class<? extends AbstractReasonerComponent>> reasonerComponents;
093 private static Collection<Class<? extends AbstractLearningProblem>> learningProblems;
094 private static Collection<Class<? extends AbstractCELA>> learningAlgorithms;
095 // you can either use the components.ini file or directly specify the classes to use
096 @Deprecated
097 private static String componentsFile = "org/dllearner/components.ini";
098 private static List<String> componentClasses = new ArrayList<String> ( Arrays.asList(new String[]{
099 "org.dllearner.kb.OWLFile",
100 "org.dllearner.kb.KBFile",
101 "org.dllearner.kb.sparql.SparqlKnowledgeSource",
102 "org.dllearner.kb.OWLAPIOntology",
103 // "org.dllearner.kb.SparqlEndpointKS",
104 //reasoners
105 "org.dllearner.reasoning.OWLAPIReasoner",
106 "org.dllearner.reasoning.fuzzydll.FuzzyOWLAPIReasoner", // added by Josue
107 "org.dllearner.reasoning.DIGReasoner",
108 "org.dllearner.reasoning.FastRetrievalReasoner",
109 "org.dllearner.reasoning.FastInstanceChecker",
110 "org.dllearner.reasoning.ProtegeReasoner",
111 "org.dllearner.reasoning.PelletReasoner",
112 //learning problems
113 "org.dllearner.learningproblems.PosNegLPStandard",
114 "org.dllearner.learningproblems.fuzzydll.FuzzyPosNegLPStandard", // added by Josue
115 "org.dllearner.learningproblems.PosNegLPStrict",
116 "org.dllearner.learningproblems.PosOnlyLP",
117 "org.dllearner.learningproblems.ClassLearningProblem",
118 //learning algorithms
119 "org.dllearner.algorithms.RandomGuesser",
120 "org.dllearner.algorithms.BruteForceLearner",
121 "org.dllearner.algorithms.refinement.ROLearner",
122 "org.dllearner.algorithms.ocel.OCEL",
123 "org.dllearner.algorithms.gp.GP",
124 "org.dllearner.algorithms.el.ELLearningAlgorithm",
125 "org.dllearner.algorithms.el.ELLearningAlgorithmDisjunctive",
126 "org.dllearner.algorithms.celoe.CELOE",
127 "org.dllearner.algorithms.fuzzydll.FuzzyCELOE", //added by Josue
128 "org.dllearner.algorithms.isle.ISLE"
129 } ));
130
131 private static ComponentManager cm = null;
132
133 // list of all configuration options of all components
134 private static Map<Class<? extends AbstractComponent>, String> componentNames;
135 private static Map<Class<? extends AbstractComponent>, List<ConfigOption<?>>> componentOptions;
136 private static Map<Class<? extends AbstractComponent>, Map<String, ConfigOption<?>>> componentOptionsByName;
137 private static Map<Class<? extends AbstractCELA>, Collection<Class<? extends AbstractLearningProblem>>> algorithmProblemsMapping;
138 private static Map<Class<? extends AbstractLearningProblem>, Collection<Class<? extends AbstractCELA>>> problemAlgorithmsMapping;
139
140 // list of default values of config options
141 // private static Map<ConfigOption<?>,Object> configOptionDefaults;
142
143 private Comparator<Class<?>> classComparator = new Comparator<Class<?>>() {
144
145 public int compare(Class<?> c1, Class<?> c2) {
146 return c1.getName().compareTo(c2.getName());
147 }
148
149 };
150
151 @SuppressWarnings("unchecked")
152 private ComponentManager() {
153
154 // read in components file
155 /*REMOVED THE BLOCK*/
156 /*List<String> componentsString;
157 if(componentClasses.length > 0) {
158 componentsString = Arrays.asList(componentClasses);
159 } else {
160 componentsString = readComponentsFile();
161 }*/
162 //List<String> componentsString2 = Arrays.asList(componentClasses);
163
164 // component list
165 components = new TreeSet<Class<? extends AbstractComponent>>(classComparator);
166 knowledgeSources = new TreeSet<Class<? extends AbstractKnowledgeSource>>(classComparator);
167 reasonerComponents = new TreeSet<Class<? extends AbstractReasonerComponent>>(classComparator);
168 learningProblems = new TreeSet<Class<? extends AbstractLearningProblem>>(classComparator);
169 learningAlgorithms = new TreeSet<Class<? extends AbstractCELA>>(classComparator);
170 algorithmProblemsMapping = new TreeMap<Class<? extends AbstractCELA>, Collection<Class<? extends AbstractLearningProblem>>>(
171 classComparator);
172
173 // create classes from strings
174 for (String componentString : componentClasses) {
175 try {
176 Class<? extends AbstractComponent> component = Class.forName(componentString).asSubclass(
177 AbstractComponent.class);
178 components.add(component);
179
180 if (AbstractKnowledgeSource.class.isAssignableFrom(component)) {
181 knowledgeSources.add((Class<? extends AbstractKnowledgeSource>) component);
182 } else if (AbstractReasonerComponent.class.isAssignableFrom(component)) {
183 reasonerComponents.add((Class<? extends AbstractReasonerComponent>) component);
184 } else if (AbstractLearningProblem.class.isAssignableFrom(component)) {
185 learningProblems.add((Class<? extends AbstractLearningProblem>) component);
186 } else if (AbstractCELA.class.isAssignableFrom(component)) {
187 Class<? extends AbstractCELA> learningAlgorithmClass = (Class<? extends AbstractCELA>) component;
188 learningAlgorithms.add(learningAlgorithmClass);
189 Collection<Class<? extends AbstractLearningProblem>> problems = (Collection<Class<? extends AbstractLearningProblem>>) invokeStaticMethod(
190 learningAlgorithmClass, "supportedLearningProblems");
191 algorithmProblemsMapping.put(learningAlgorithmClass, problems);
192 }
193
194 } catch (ClassNotFoundException e) {
195 e.printStackTrace();
196 }
197 }
198 problemAlgorithmsMapping = Maps.revertCollectionMap(algorithmProblemsMapping);
199
200 componentNames = new HashMap<Class<? extends AbstractComponent>, String>();
201 // read in all configuration options
202 componentOptions = new HashMap<Class<? extends AbstractComponent>, List<ConfigOption<?>>>();
203 componentOptionsByName = new HashMap<Class<? extends AbstractComponent>, Map<String, ConfigOption<?>>>();
204 // configOptionDefaults = new HashMap<ConfigOption<?>,Object>();
205
206 for (Class<? extends AbstractComponent> component : components) {
207
208 String name = (String) invokeStaticMethod(component, "getName");
209 componentNames.put(component, name);
210
211 // assign options to components
212 List<ConfigOption<?>> options = (List<ConfigOption<?>>) invokeStaticMethod(component,
213 "createConfigOptions");
214 componentOptions.put(component, options);
215
216 // make config options accessible by name
217 Map<String, ConfigOption<?>> byName = new HashMap<String, ConfigOption<?>>();
218 for (ConfigOption<?> option : options) {
219 byName.put(option.getName(), option);
220 }
221 componentOptionsByName.put(component, byName);
222
223 }
224
225 }
226
227 /**
228 * Gets the singleton instance of <code>ComponentManager</code>.
229 * @return The singleton <code>ComponentManager</code> instance.
230 */
231 public static ComponentManager getInstance() {
232 if(cm == null) {
233 cm = new ComponentManager();
234 }
235 return cm;
236 }
237
238 /**
239 * Set the classes, which can be used as components. By default,
240 * this is read from components.ini, but this method can be used
241 * to set the components programmatically. This method must be
242 * used before the first call to {@link #getInstance()}, otherwise
243 * it has no effect.
244 *
245 * @param componentClasses A list of class names, e.g.
246 * org.dllearner.refinement.ROLearner.
247 */
248 public static void setComponentClasses(String[] componentClasses) {
249 ComponentManager.componentClasses = new ArrayList<String> (Arrays.asList(componentClasses));
250 }
251
252 @Deprecated
253 private static List<String> readComponentsFile() {
254 List<String> componentStrings = new LinkedList<String>();
255
256 try {
257
258 InputStream is = ComponentManager.class.getClassLoader().getResourceAsStream(componentsFile);
259 DataInputStream in = new DataInputStream(is);
260 BufferedReader br = new BufferedReader(new InputStreamReader(in));
261 String line;
262
263 while ((line = br.readLine()) != null) {
264 if (!(line.startsWith("#") || line.startsWith("//") || line.startsWith("%") || line
265 .length() <= 1)) {
266 componentStrings.add(line);
267 }
268 }
269
270 in.close();
271 } catch (IOException e) {
272 e.printStackTrace();
273 }
274
275 return componentStrings;
276 }
277
278 /**
279 * Convenience method for testing purposes. If you know that the type of the
280 * value is correct, it is preferable to create a ConfigEntry object and
281 * apply it to the component (no type checking necessary).
282 *
283 * @param <T> Type of the config option (Integer, String etc.).
284 * @param component A component.
285 * @param optionName The name of the config option.
286 * @param value The value of the config option.
287 */
288 @SuppressWarnings("unchecked")
289 public <T> void applyConfigEntry(AbstractComponent component, String optionName, T value) {
290 logger.trace(component);
291 logger.trace(optionName);
292 logger.trace(value);
293 logger.trace(value.getClass());
294 // first we look whether the component is registered
295 if (components.contains(component.getClass())) {
296
297 // look for a config option with the specified name
298 ConfigOption<?> option = (ConfigOption<?>) componentOptionsByName.get(
299 component.getClass()).get(optionName);
300 if (option != null) {
301 // check whether the given object has the correct type
302 if (!option.checkType(value)) {
303 System.out.println("Warning: value " + value + " is not valid for option "
304 + optionName + " in component " + component
305 + ". It does not have the correct type.");
306 return;
307 }
308
309 // we have checked the type, hence it should now be safe to
310 // typecast and
311 // create a ConfigEntry object
312 ConfigEntry<T> entry = null;
313 try {
314 entry = new ConfigEntry<T>((ConfigOption<T>) option, value);
315 component.applyConfigEntry(entry);
316 pool.addConfigEntry(component, entry, true);
317 } catch (InvalidConfigOptionValueException e) {
318 pool.addConfigEntry(component, entry, false);
319 System.out.println("Warning: value " + value + " is not valid for option "
320 + optionName + " in component " + component);
321 }
322 } else {
323 logger.warn("Warning: undefined option " + optionName + " in component "
324 + component);
325 }
326 } else {
327 logger.warn("Warning: unregistered component " + component);
328 }
329 }
330
331 public ComponentPool getPool() {
332 return pool;
333 }
334
335 /**
336 * Applies a config entry to a component. If the entry is not valid, the method
337 * prints an exception and returns false.
338 * @param <T> Type of the config option.
339 * @param component A component object.
340 * @param entry The configuration entry to set.
341 * @return True of the config entry could be applied succesfully, otherwise false.
342 */
343 public <T> boolean applyConfigEntry(AbstractComponent component, ConfigEntry<T> entry) {
344 try {
345 component.applyConfigEntry(entry);
346 pool.addConfigEntry(component, entry, true);
347 return true;
348 } catch (InvalidConfigOptionValueException e) {
349 pool.addConfigEntry(component, entry, false);
350 e.printStackTrace();
351 return false;
352 }
353 }
354
355 /**
356 * Factory method for creating a knowledge source.
357 *
358 * @param <T> The type of this method is a subclass of knowledge source.
359 * @param source A registered knowledge source component.
360 * @return An instance of the given knowledge source class.
361 */
362 public <T extends AbstractKnowledgeSource> T knowledgeSource(Class<T> source) {
363 if (!knowledgeSources.contains(source)) {
364 logger.warn("Warning: knowledge source " + source
365 + " is not a registered knowledge source component.");
366 }
367
368 T ks = invokeConstructor(source, new Class[] {}, new Object[] {});
369 pool.registerComponent(ks);
370 return ks;
371 }
372
373 /**
374 * Factory method for creating a reasoner component from a single
375 * knowledge source. Example
376 * call: reasoner(OWLAPIReasoner.class, ks) where ks is a
377 * knowledge source object.
378 * @see #reasoner(Class, Set)
379 * @param <T> The type of this method is a subclass of reasoner component.
380 * @param reasoner A class object, where the class is subclass of ReasonerComponent.
381 * @param source A knowledge source.
382 * @return A reasoner component.
383 */
384 public <T extends AbstractReasonerComponent> T reasoner(Class<T> reasoner,
385 AbstractKnowledgeSource source) {
386 Set<AbstractKnowledgeSource> sources = new HashSet<AbstractKnowledgeSource>();
387 sources.add(source);
388 return reasoner(reasoner, sources);
389 }
390
391 /**
392 * Factory method for creating a reasoner component from a set of
393 * knowledge sources.
394 * @see #reasoner(Class, AbstractKnowledgeSource)
395 * @param <T> The type of this method is a subclass of reasoner component.
396 * @param reasoner A class object, where the class is subclass of ReasonerComponent.
397 * @param sources A set of knowledge sources.
398 * @return A reasoner component.
399 */
400 public <T extends AbstractReasonerComponent> T reasoner(Class<T> reasoner,
401 Set<AbstractKnowledgeSource> sources) {
402 if (!reasonerComponents.contains(reasoner)) {
403 System.err.println("Warning: reasoner component " + reasoner
404 + " is not a registered reasoner component.");
405 }
406
407 T rc = invokeConstructor(reasoner, new Class[] { Set.class },
408 new Object[] { sources });
409 pool.registerComponent(rc);
410 return rc;
411 }
412
413 /**
414 * Factory method for creating a reasoner component from a set of
415 * knowledge sources.
416 * @see #reasoner(Class, AbstractKnowledgeSource)
417 * @param <T> The type of this method is a subclass of reasoner component.
418 * @param reasoner A class object, where the class is subclass of ReasonerComponent.
419 * @param sources A set of knowledge sources.
420 * @return A reasoner component.
421 */
422 public <T extends AbstractReasonerComponent> T reasoner(Class<T> reasoner,
423 AbstractKnowledgeSource ... sources) {
424 Set<AbstractKnowledgeSource> s = new HashSet<AbstractKnowledgeSource>();
425 for(AbstractKnowledgeSource source : sources) {
426 s.add(source);
427 }
428 return reasoner(reasoner, s);
429 }
430
431 /**
432 * This method returns an instance of <code>ReasonerComponent</code>. The
433 * difference between <code>ReasonerComponent</code> and <code>ReasonerComponent</code>
434 * is that the former delegates all calls to the latter and collects statistics
435 * while doing this. This means that the reasoning service enables the
436 * collection of query information, while the <code>ReasonerComponent</code>
437 * implements the actual reasoning methods defined by the <code>Reasoner</code>
438 * interface.
439 *
440 * @param reasoner A reasoner component.
441 * @return The reasoning service encapsulating the reasoner.
442 */
443 // public ReasonerComponent reasoningService(ReasonerComponent reasoner) {
444 // return new ReasonerComponent(reasoner);
445 // }
446
447 /**
448 * Factory method for creating a learning problem component.
449 * @param <T> The type of this method is a subclass of learning problem.
450 * @param lpClass A class object, where the class is a subclass of learning problem.
451 * @param reasoner A reasoning service object.
452 * @return A learning problem component.
453 */
454 public <T extends AbstractLearningProblem> T learningProblem(Class<T> lpClass, AbstractReasonerComponent reasoner) {
455 if (!learningProblems.contains(lpClass)) {
456 System.err.println("Warning: learning problem " + lpClass
457 + " is not a registered learning problem component.");
458 }
459
460 T lp = invokeConstructor(lpClass, new Class[] { AbstractReasonerComponent.class },
461 new Object[] { reasoner });
462 pool.registerComponent(lp);
463 return lp;
464 }
465
466 /**
467 * Factory method for creating a learning algorithm, which
468 * automagically calls the right constructor for the given problem.
469 * @param <T> The type of this method is a subclass of learning algorithm.
470 * @param laClass A class object, where the class is subclass of learning algorithm.
471 * @param lp A learning problem, which the algorithm should try to solve.
472 * @param rs A reasoning service for querying the background knowledge of this learning problem.
473 * @return A learning algorithm component.
474 * @throws LearningProblemUnsupportedException Thrown when the learning problem and
475 * the learning algorithm are not compatible.
476 */
477 public <T extends AbstractCELA> T learningAlgorithm(Class<T> laClass, AbstractLearningProblem lp, AbstractReasonerComponent rs) throws LearningProblemUnsupportedException {
478 if (!learningAlgorithms.contains(laClass)) {
479 System.err.println("Warning: learning algorithm " + laClass
480 + " is not a registered learning algorithm component.");
481 }
482
483 // find the right constructor: use the one that is registered and
484 // has the class of the learning problem as a subclass
485 Class<? extends AbstractLearningProblem> constructorArgument = null;
486 for (Class<? extends AbstractLearningProblem> problemClass : algorithmProblemsMapping.get(laClass)) {
487 if (problemClass.isAssignableFrom(lp.getClass())) {
488 constructorArgument = problemClass;
489 }
490 }
491
492 if (constructorArgument == null) {
493 throw new LearningProblemUnsupportedException(lp.getClass(), laClass, algorithmProblemsMapping.get(laClass));
494 // System.err.println("Warning: No suitable constructor registered for algorithm "
495 // + laClass.getName() + " and problem " + lp.getClass().getName()
496 // + ". Registered constructors for " + laClass.getName() + ": "
497 // + algorithmProblemsMapping.get(laClass) + ".");
498 // return null;
499 }
500
501 T la = invokeConstructor(laClass, new Class[] { constructorArgument, AbstractReasonerComponent.class }, new Object[] { lp, rs });
502 pool.registerComponent(la);
503 return la;
504 }
505 //
506 // public <T extends LearningAlgorithm> T learningAlgorithm(Class<T> laClass, KnowledgeSource ks) {
507 // T la = invokeConstructor(laClass, new Class[] { KnowledgeSource.class }, new Object[] { ks });
508 // return la;
509 // }
510
511 /**
512 * The <code>ComponentManager</code> factory methods produce component
513 * instances, which can be freed using this method. Calling the factory
514 * methods without freeing components when they are not used anymore
515 * can (in theory) cause memory problems.
516 *
517 * @param component The component to free.
518 */
519 public void freeComponent(AbstractComponent component) {
520 pool.unregisterComponent(component);
521 }
522
523 /**
524 * Frees all references to components created by <code>ComponentManager</code>.
525 * @see #freeComponent(AbstractComponent)
526 */
527 public synchronized void freeAllComponents() {
528 pool.clearComponents();
529 }
530
531 /**
532 * Gets the value of a config option of the specified component.
533 * This is done by first checking, which value the given option
534 * was set to using {@link #applyConfigEntry(AbstractComponent, ConfigEntry)}.
535 * If the value has not been changed, the default value for this
536 * option is returned. Note, that this method will not work properly
537 * if the component options are changed internally surpassing the
538 * component manager (which is discouraged).
539 *
540 * @param <T> The type of the config option, e.g. String, boolean, integer.
541 * @param component The component, which has the specified option.
542 * @param option The option for which we want to know its value.
543 * @return The value of the specified option in the specified component.
544 */
545 public <T> T getConfigOptionValue(AbstractComponent component, ConfigOption<T> option) {
546 T object = pool.getLastValidConfigValue(component, option);
547 if(object==null) {
548 return option.getDefaultValue();
549 } else {
550 return object;
551 }
552 }
553
554 /**
555 * Works as {@link #getConfigOptionValue(AbstractComponent, ConfigOption)},
556 * but using the name of the option instead of a <code>ConfigOption</code>
557 * object.
558 * @see #getConfigOptionValue(AbstractComponent, ConfigOption)
559 * @param component A component.
560 * @param optionName A valid option name for this component.
561 * @return The value of the specified option in the specified component.
562 */
563 public Object getConfigOptionValue(AbstractComponent component, String optionName) {
564 ConfigOption<?> option = (ConfigOption<?>) componentOptionsByName.get(
565 component.getClass()).get(optionName);
566 return getConfigOptionValue(component, option);
567 }
568
569 // convenience method for invoking a static method;
570 // used as a central point for exception handling for Java reflection
571 // static method calls
572 private static Object invokeStaticMethod(Class<?> clazz, String methodName, Object... args) {
573 // unfortunately Java does not seem to offer a way to call
574 // a static method given a class object directly, so we have
575 // to use reflection
576 try {
577 Method method = clazz.getMethod(methodName);
578 return method.invoke(null, args);
579 } catch (SecurityException e) {
580 e.printStackTrace();
581 } catch (NoSuchMethodException e) {
582 e.printStackTrace();
583 } catch (IllegalArgumentException e) {
584 e.printStackTrace();
585 } catch (IllegalAccessException e) {
586 e.printStackTrace();
587 } catch (InvocationTargetException e) {
588 e.printStackTrace();
589 }
590
591 return null;
592 }
593
594 // convenience method for invoking a constructor;
595 // used as a central point for exception handling for Java reflection
596 // constructor calls
597 private <T> T invokeConstructor(Class<T> clazz, Class<?>[] argumentClasses,
598 Object[] argumentObjects) {
599 try {
600 Constructor<T> constructor = clazz.getConstructor(argumentClasses);
601 return constructor.newInstance(argumentObjects);
602 } catch (IllegalArgumentException e) {
603 e.printStackTrace();
604 } catch (InstantiationException e) {
605 e.printStackTrace();
606 } catch (IllegalAccessException e) {
607 e.printStackTrace();
608 } catch (InvocationTargetException e) {
609 e.printStackTrace();
610 } catch (SecurityException e) {
611 e.printStackTrace();
612 } catch (NoSuchMethodException e) {
613 e.printStackTrace();
614 }
615 return null;
616 }
617
618 /**
619 * Returns the available options of the specified component.
620 * @param componentClass The class object of a component.
621 * @return A list of available configuration options of the specified component.
622 */
623 public static List<ConfigOption<?>> getConfigOptions(Class<? extends AbstractComponent> componentClass) {
624 if (!components.contains(componentClass)) {
625 System.err.println("Warning: component " + componentClass
626 + " is not a registered component. [ComponentManager.getConfigOptions]");
627 }
628 return componentOptions.get(componentClass);
629 }
630
631 /**
632 * Returns a <code>ConfigOption</code> object given a component and
633 * the option name.
634 * @param component A component class object.
635 * @param name A valid configuration option name for the component.
636 * @return A <code>ConfigOption</code> object for the specified component class and option name.
637 */
638 public ConfigOption<?> getConfigOption(Class<? extends AbstractComponent> component, String name) {
639 return componentOptionsByName.get(component).get(name);
640 }
641
642 /**
643 * Returns the name of a component.
644 * @param component A component class object.
645 * @return The name of the component.
646 */
647 public String getComponentName(Class<? extends AbstractComponent> component) {
648 return componentNames.get(component);
649 }
650
651 /**
652 * Returns a list of all available components in this instance
653 * of <code>ComponentManager</code>.
654 * @return the components A list of component classes available in this
655 * instance of <code>ComponentManager</code>.
656 */
657 public List<Class<? extends AbstractComponent>> getComponents() {
658 return new LinkedList<Class<? extends AbstractComponent>>(components);
659 }
660
661 /**
662 * Returns a list of all available knowledge sources in this instance
663 * of <code>ComponentManager</code>.
664 * @return the components A list of knowledge source component classes available in this
665 * instance of <code>ComponentManager</code>.
666 */
667 public List<Class<? extends AbstractKnowledgeSource>> getKnowledgeSources() {
668 return new LinkedList<Class<? extends AbstractKnowledgeSource>>(knowledgeSources);
669 }
670
671 /**
672 * Returns a list of all available reasoners in this instance
673 * of <code>ComponentManager</code>.
674 * @return the components A list of reasoner component classes available in this
675 * instance of <code>ComponentManager</code>.
676 */
677 public List<Class<? extends AbstractReasonerComponent>> getReasonerComponents() {
678 return new LinkedList<Class<? extends AbstractReasonerComponent>>(reasonerComponents);
679 }
680
681 /**
682 * Returns a list of all available learning problems in this instance
683 * of <code>ComponentManager</code>.
684 * @return the components A list of learning problem classes available in this
685 * instance of <code>ComponentManager</code>.
686 */
687 public List<Class<? extends AbstractLearningProblem>> getLearningProblems() {
688 return new LinkedList<Class<? extends AbstractLearningProblem>>(learningProblems);
689 }
690
691 /**
692 * Returns the set of learning algorithms, which support the given learning problem type.
693 * @param learningProblem A learning problem type.
694 * @return The set of learning algorithms applicable for this learning problem.
695 */
696 public List<Class<? extends AbstractCELA>> getApplicableLearningAlgorithms(Class<? extends AbstractLearningProblem> learningProblem) {
697 List<Class<? extends AbstractCELA>> algorithms = new LinkedList<Class<? extends AbstractCELA>>();
698 for(Entry<Class<? extends AbstractLearningProblem>,Collection<Class<? extends AbstractCELA>>> entry : problemAlgorithmsMapping.entrySet()) {
699 Class<? extends AbstractLearningProblem> prob = entry.getKey();
700 if(prob.isAssignableFrom(learningProblem)) {
701 algorithms.addAll(entry.getValue());
702 }
703 }
704 // System.out.println(learningProblem + ": " + algorithms);
705 return algorithms;
706 }
707
708 /**
709 * Returns a list of all available learning algorithms in this instance
710 * of <code>ComponentManager</code>.
711 * @return the components A list of learning algorithm classes available in this
712 * instance of <code>ComponentManager</code>.
713 */
714 public List<Class<? extends AbstractCELA>> getLearningAlgorithms() {
715 return new LinkedList<Class<? extends AbstractCELA>>(learningAlgorithms);
716 }
717
718
719 /**
720 * Retuns a list of all instanciated and registered Components
721 * @return Currently active components.
722 */
723 public List<AbstractComponent> getLiveComponents(){
724 return pool.getComponents();
725 }
726
727 /**
728 * Retuns a list of all instanciated and registered LearningAlgorithm
729 * @return Currently active learning algorithms.
730 */
731 public List<AbstractCELA> getLiveLearningAlgorithms(){
732 List<AbstractCELA> list = new ArrayList<AbstractCELA>();
733 for (AbstractComponent component : cm.getLiveComponents()) {
734 if(component instanceof AbstractCELA){
735 list.add((AbstractCELA) component);
736 }
737
738 }
739 return list;
740 }
741
742 /**
743 * Retuns a list of all instanciated and registered KnowledgeSource
744 * @return Currently active knowledge sources.
745 */
746 public List<AbstractKnowledgeSource> getLiveKnowledgeSources(){
747 List<AbstractKnowledgeSource> list = new ArrayList<AbstractKnowledgeSource>();
748 for (AbstractComponent component : cm.getLiveComponents()) {
749 if(component instanceof AbstractKnowledgeSource){
750 list.add((AbstractKnowledgeSource) component);
751 }
752
753 }
754 return list;
755 }
756
757 }