package org.shininet.bukkit.itemrenamer.component;
import java.util.Map;
import javax.annotation.Nonnull;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.plugin.Plugin;
import com.google.common.base.Supplier;
import com.google.common.collect.Maps;
import com.google.common.eventbus.EventBus;
import com.google.common.util.concurrent.UncheckedExecutionException;
public class PluginComponent extends AbstractBukkitComponent {
private Map<String, Supplier<? extends Component>> suppliers = Maps.newHashMap();
private Map<String, Component> components = Maps.newHashMap();
/**
* Add a new component that will be constructed and registered if the given plugin is enabled.
* @param pluginName - the plugin to wait for.
* @param supplier - the supplier that will be activated when the given plugin has been enabled.
* @return This plugin component, for chaining,
*/
public PluginComponent add(String pluginName, Supplier<? extends Component> supplier) {
suppliers.put(pluginName, supplier);
// Register the component if the plugin has already been enabled
if (Bukkit.getPluginManager().isPluginEnabled(pluginName)) {
onPluginEnabled(Bukkit.getPluginManager().getPlugin(pluginName));
}
return this;
}
/**
* Add a new component that will be constructed and registered if the given plugin is enabled.
* @param pluginName - the plugin to wait for.
* @param componentClass - the class of the component to construct.
* @return This plugin component, for chaining,
*/
public PluginComponent add(String pluginName, Class<? extends Component> componentClass) {
return add(pluginName, newSupplier(componentClass));
}
/**
* Retrieve a component by its the associated plugin, if it has been constructed.
* @param pluginName - the associated plugin.
* @return The component, or NULL.
*/
public Component get(String pluginName) {
return components.get(pluginName);
}
@Override
protected void onRegistered(@Nonnull Plugin plugin, EventBus bus) {
super.onRegistered(plugin, bus);
// Delayed enabled events
for (Plugin target : Bukkit.getPluginManager().getPlugins()) {
if (target.isEnabled()) {
onPluginEnabled(target);
}
}
}
@Override
protected void onUnregistered(@Nonnull Plugin plugin) {
for (Component component : components.values())
component.unregister(registered);
super.onUnregistered(plugin);
}
/**
* Invoked when we have detected that a plugin has been enabled.
* @param plugin - the enabled plugin.
*/
private void onPluginEnabled(Plugin plugin) {
String key = plugin.getName();
Supplier<? extends Component> supplier = suppliers.get(key);
// Only register the component once
if (isRegistered() && supplier != null) {
Component component = components.get(key);
// Construct and register the component
if (component == null)
components.put(key, component = supplier.get());
if (!component.isRegistered())
component.register(plugin, bus);
}
}
/**
* Invoked when a plugin has been disabled.
* @param plugin - the disabled plugin.
*/
private void onPluginDisabled(Plugin plugin) {
Component component = components.get(plugin.getName());
if (component != null) {
component.unregister(registered);
}
}
@EventHandler
public void onPluginEnabled(PluginEnableEvent e) {
onPluginEnabled(e.getPlugin());
}
@EventHandler
public void onPluginDisabled(PluginDisableEvent e) {
onPluginDisabled(e.getPlugin());
}
@Override
protected boolean requireBukkit() {
return true;
}
@Override
protected boolean requireEventBus() {
return false;
}
/**
* Return a supplier that constructs instances of the given class using the no-argument constructor.
* @param clazz - the class.
* @return A new supplier.
*/
private static <T extends Component> Supplier<T> newSupplier(final Class<T> clazz) {
return new Supplier<T>() {
@Override
public T get() {
try {
return clazz.newInstance();
} catch (Exception e) {
throw new UncheckedExecutionException("Cannot construct instance.", e);
}
}
};
}
}