// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea
// Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com
// Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
// Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
package graphtea.platform.extension;
import graphtea.platform.Application;
import graphtea.platform.StaticUtils;
import graphtea.platform.core.AbstractAction;
import graphtea.platform.core.BlackBoard;
import graphtea.platform.core.exception.ExceptionHandler;
import graphtea.platform.preferences.lastsettings.StorableOnExit;
import java.io.File;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Vector;
/**
* The base class for loading extensions.
* This class performs loading and reloading of extensions, (from their source (.class or anyother format) files)
*
* @author Azin Azadi
*/
public class ExtensionLoader implements StorableOnExit {
private static HashSet<ExtensionHandler> registeredExtensionHandlers = new HashSet<>();
private static HashSet<UnknownExtensionLoader> registeredUnknownExtensionLoaders = new HashSet<>();
// categorises the known extensions on their type. The type (eg report, generator, ...) is identified
// by the respective ExtensionHandler
public static HashMap<Class<? extends ExtensionHandler>, Vector> extensionsList = new HashMap<>();
// maps an extension class (eg GeneratePath), to the loaded AbstractAction
public static HashMap<String, AbstractAction> loadedInstances = new HashMap<>();
/**
* Registers extHandler as an extension handler, so after this new extension that are loaded
* to GraphTea will be given to handler.
* <p/>
* calling this method will not affect previously loaded extensions.
*
* @param extHandler The extension handler
*/
public static void registerExtensionHandler(ExtensionHandler extHandler) {
registeredExtensionHandlers.add(extHandler);
}
public static HashSet<ExtensionHandler> getRegisteredExtensionHandlers() {
return registeredExtensionHandlers;
}
/**
* register e as an unKnownExtensionLoader, which GraphTea will try to load "not .class files" with them
*
* @param e The extension loader
*/
public static void registerUnknownExtensionLoader(UnknownExtensionLoader e) {
registeredUnknownExtensionLoaders.add(e);
}
/**
* gets e as an extension and tries to create Its relating AbstractAction
* using registered ExtensionHandlers
*
* This should be the only place to handle extensions otherwise we are in problem,
* because here we keep list of handled extensions for further uses. everything else will
* not be in this list.
*/
public static AbstractAction handleExtension(BlackBoard b, Object e) {
AbstractAction a = null;
for (ExtensionHandler handler : registeredExtensionHandlers) {
AbstractAction ret = handler.handle(b, e);
if (ret != null){
if (a == null) {
a = ret;
}
if (!extensionsList.containsKey(handler.getClass())){
extensionsList.put(handler.getClass(), new Vector());
}
extensionsList.get(handler.getClass()).add(e);
loadedInstances.put(e.getClass().getName(), a);
}
}
return a;
}
/**
* returns an instance of extensionClass if the given extensionClass implements Extension (BasicExtension)
* or has default constructor, otherwise it returns null
*
* @param extensionClass the extension class
* @return an object of the given extension
*/
public static Object loadExtension(Class extensionClass) {
Object ret = null;
try {
if (BasicExtension.class.isAssignableFrom(extensionClass)) {
Constructor[] cs = extensionClass.getConstructors();
for (Constructor c : cs) {
Class[] p = c.getParameterTypes();
if (p.length == 1 && p[0].equals(BlackBoard.class)) {
ret = extensionClass.getConstructor(BlackBoard.class).newInstance(Application.blackboard);
break;
}
}
if (ret == null && extensionClass.getConstructor() != null) {
ret = extensionClass.newInstance();
}
}
if (ret != null) {
SETTINGS.registerSetting(ret, "Extention Options");
}
return ret;
} catch (Exception e) {
System.err.println(extensionClass);
ExceptionHandler.catchException(e);
StaticUtils.addExceptiontoLog(e, Application.blackboard);
}
return ret;
}
/**
* returns an instance of extensionClsas if the given extensionClass implements Extension, otherwise it returns null
*
* @param unknownFile The given unknown extension
*/
public static Extension loadUnknownExtension(File unknownFile, BlackBoard blackboard) {
for (UnknownExtensionLoader loader : registeredUnknownExtensionLoaders) {
Extension extension = loader.load(unknownFile, blackboard);
if (extension != null)
return extension;
}
return null;
}
}