2017-07-25 21:50:30 -07:00
|
|
|
package org.nwapw.abacus.plugin;
|
|
|
|
|
2017-07-26 10:15:22 -07:00
|
|
|
import org.nwapw.abacus.function.Function;
|
2017-07-27 10:38:18 -07:00
|
|
|
import org.nwapw.abacus.function.Operator;
|
2017-07-26 10:15:22 -07:00
|
|
|
|
2017-07-25 21:50:30 -07:00
|
|
|
import java.lang.reflect.InvocationTargetException;
|
2017-07-27 10:38:18 -07:00
|
|
|
import java.util.*;
|
2017-07-25 21:50:30 -07:00
|
|
|
|
2017-07-26 10:15:22 -07:00
|
|
|
/**
|
|
|
|
* A class that controls instances of plugins, allowing for them
|
|
|
|
* to interact with each other and the calculator.
|
|
|
|
*/
|
2017-07-25 21:50:30 -07:00
|
|
|
public class PluginManager {
|
|
|
|
|
2017-07-26 10:15:22 -07:00
|
|
|
/**
|
|
|
|
* A list of loaded plugins.
|
|
|
|
*/
|
2017-07-27 18:19:12 -07:00
|
|
|
private List<Plugin> plugins;
|
2017-07-26 10:15:22 -07:00
|
|
|
/**
|
|
|
|
* List of functions that have been cached,
|
|
|
|
* that is, found in a plugin and returned.
|
|
|
|
*/
|
2017-07-27 18:19:12 -07:00
|
|
|
private Map<String, Function> cachedFunctions;
|
2017-07-27 10:38:18 -07:00
|
|
|
/**
|
|
|
|
* List of operators tha have been cached,
|
|
|
|
* that is, found in a plugin and returned.
|
|
|
|
*/
|
2017-07-27 18:19:12 -07:00
|
|
|
private Map<String, Operator> cachedOperators;
|
2017-07-27 13:26:17 -07:00
|
|
|
/**
|
|
|
|
* List of all functions loaded by the plugins.
|
|
|
|
*/
|
2017-07-27 18:19:12 -07:00
|
|
|
private Set<String> allFunctions;
|
2017-07-27 13:26:17 -07:00
|
|
|
/**
|
|
|
|
* List of all operators loaded by the plugins.
|
|
|
|
*/
|
2017-07-27 18:19:12 -07:00
|
|
|
private Set<String> allOperators;
|
2017-07-27 13:26:17 -07:00
|
|
|
/**
|
|
|
|
* The list of plugin listeners attached to this instance.
|
|
|
|
*/
|
2017-07-27 18:19:12 -07:00
|
|
|
private Set<PluginListener> listeners;
|
2017-07-25 21:50:30 -07:00
|
|
|
|
2017-07-26 10:15:22 -07:00
|
|
|
/**
|
|
|
|
* Creates a new plugin manager.
|
|
|
|
*/
|
2017-07-25 21:50:30 -07:00
|
|
|
public PluginManager(){
|
|
|
|
plugins = new ArrayList<>();
|
2017-07-26 10:15:22 -07:00
|
|
|
cachedFunctions = new HashMap<>();
|
2017-07-27 12:53:58 -07:00
|
|
|
cachedOperators = new HashMap<>();
|
2017-07-27 13:26:17 -07:00
|
|
|
allFunctions = new HashSet<>();
|
|
|
|
allOperators = new HashSet<>();
|
2017-07-27 14:06:04 -07:00
|
|
|
listeners = new HashSet<>();
|
2017-07-25 21:50:30 -07:00
|
|
|
}
|
|
|
|
|
2017-07-27 10:58:11 -07:00
|
|
|
/**
|
|
|
|
* Searches the plugin list for a certain value, retrieving the Plugin's
|
|
|
|
* list of items of the type using the setFunction and getting the value
|
|
|
|
* of it is available via getFunction. If the value is contained
|
|
|
|
* in the cache, it returns the cached value instead.
|
|
|
|
* @param plugins the plugin list to search.
|
|
|
|
* @param cache the cache to use
|
|
|
|
* @param setFunction the function to retrieve a set of available T's from the plugin
|
|
|
|
* @param getFunction the function to get the T value under the given name
|
|
|
|
* @param name the name to search for
|
|
|
|
* @param <T> the type of element being search
|
|
|
|
* @return the retrieved element, or null if it was not found.
|
|
|
|
*/
|
2017-07-27 10:38:18 -07:00
|
|
|
private static <T> T searchCached(Collection<Plugin> plugins, Map<String, T> cache,
|
|
|
|
java.util.function.Function<Plugin, Set<String>> setFunction,
|
|
|
|
java.util.function.BiFunction<Plugin, String, T> getFunction,
|
|
|
|
String name){
|
|
|
|
if(cache.containsKey(name)) return cache.get(name);
|
|
|
|
|
|
|
|
T loadedValue = null;
|
|
|
|
for(Plugin plugin : plugins){
|
|
|
|
if(setFunction.apply(plugin).contains(name)){
|
|
|
|
loadedValue = getFunction.apply(plugin, name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cache.put(name, loadedValue);
|
|
|
|
return loadedValue;
|
|
|
|
}
|
2017-07-26 10:15:22 -07:00
|
|
|
/**
|
|
|
|
* Gets a function under the given name.
|
|
|
|
* @param name the name of the function
|
|
|
|
* @return the function under the given name.
|
|
|
|
*/
|
|
|
|
public Function functionFor(String name){
|
2017-07-27 10:38:18 -07:00
|
|
|
return searchCached(plugins, cachedFunctions, Plugin::providedFunctions, Plugin::getFunction, name);
|
|
|
|
}
|
2017-07-25 21:50:30 -07:00
|
|
|
|
2017-07-27 10:38:18 -07:00
|
|
|
/**
|
|
|
|
* Gets an operator under the given name.
|
|
|
|
* @param name the name of the operator.
|
|
|
|
* @return the operator under the given name.
|
|
|
|
*/
|
|
|
|
public Operator operatorFor(String name){
|
|
|
|
return searchCached(plugins, cachedOperators, Plugin::providedOperators, Plugin::getOperator, name);
|
2017-07-25 21:50:30 -07:00
|
|
|
}
|
|
|
|
|
2017-07-26 10:15:22 -07:00
|
|
|
/**
|
|
|
|
* Adds an instance of Plugin that already has been instantiated.
|
|
|
|
* @param plugin the plugin to add.
|
|
|
|
*/
|
2017-07-25 21:50:30 -07:00
|
|
|
public void addInstantiated(Plugin plugin){
|
|
|
|
plugins.add(plugin);
|
|
|
|
}
|
|
|
|
|
2017-07-26 10:15:22 -07:00
|
|
|
/**
|
|
|
|
* Instantiates a class of plugin, and adds it to this
|
|
|
|
* plugin manager.
|
|
|
|
* @param newClass the new class to instantiate.
|
|
|
|
*/
|
2017-07-25 21:50:30 -07:00
|
|
|
public void addClass(Class<?> newClass){
|
|
|
|
if(!Plugin.class.isAssignableFrom(newClass)) return;
|
|
|
|
try {
|
|
|
|
addInstantiated((Plugin) newClass.getConstructor(PluginManager.class).newInstance(this));
|
|
|
|
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
|
|
|
|
e.printStackTrace();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-27 13:26:17 -07:00
|
|
|
/**
|
|
|
|
* Loads all the plugins in the PluginManager.
|
|
|
|
*/
|
|
|
|
public void load(){
|
|
|
|
for(Plugin plugin : plugins) plugin.enable();
|
|
|
|
for(Plugin plugin : plugins){
|
|
|
|
allFunctions.addAll(plugin.providedFunctions());
|
|
|
|
allOperators.addAll(plugin.providedOperators());
|
|
|
|
}
|
2017-07-27 14:06:04 -07:00
|
|
|
listeners.forEach(e -> e.onLoad(this));
|
2017-07-27 13:26:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unloads all the plugins in the PluginManager.
|
|
|
|
*/
|
|
|
|
public void unload(){
|
|
|
|
for(Plugin plugin : plugins) plugin.disable();
|
|
|
|
allFunctions.clear();
|
|
|
|
allOperators.clear();
|
2017-07-27 14:06:04 -07:00
|
|
|
listeners.forEach(e -> e.onUnload(this));
|
2017-07-27 13:26:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reloads all the plugins in the PluginManager.
|
|
|
|
*/
|
|
|
|
public void reload(){
|
|
|
|
unload();
|
|
|
|
reload();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets all the functions loaded by the Plugin Manager.
|
|
|
|
* @return the set of all functions that were loaded.
|
|
|
|
*/
|
2017-07-27 18:19:12 -07:00
|
|
|
public Set<String> getAllFunctions() {
|
2017-07-27 13:26:17 -07:00
|
|
|
return allFunctions;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets all the operators loaded by the Plugin Manager.
|
|
|
|
* @return the set of all operators that were loaded.
|
|
|
|
*/
|
2017-07-27 18:19:12 -07:00
|
|
|
public Set<String> getAllOperators() {
|
2017-07-27 13:26:17 -07:00
|
|
|
return allOperators;
|
|
|
|
}
|
2017-07-27 14:06:04 -07:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds a plugin change listener to this plugin manager.
|
|
|
|
* @param listener the listener to add.
|
|
|
|
*/
|
|
|
|
public void addListener(PluginListener listener){
|
|
|
|
listeners.add(listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove the plugin change listener from this plugin manager.
|
|
|
|
* @param listener the listener to remove.
|
|
|
|
*/
|
|
|
|
public void removeListener(PluginListener listener){
|
|
|
|
listeners.remove(listener);
|
|
|
|
}
|
|
|
|
|
2017-07-25 21:50:30 -07:00
|
|
|
}
|