/src/us/icebrg/imp/IMP.java
Java | 513 lines | 243 code | 79 blank | 191 comment | 28 complexity | 70862f453d0ba35dbf665034a861f366 MD5 | raw file
Possible License(s): GPL-3.0
- package us.icebrg.imp;
- import java.util.logging.Level;
- import us.icebrg.imp.chat.ChatModule;
- import us.icebrg.imp.government.GovernmentModule;
- import us.icebrg.imp.transportation.Transportation;
- import com.google.gson.Gson;
- import com.google.gson.GsonBuilder;
- import com.mongodb.DB;
- import com.mongodb.DBCollection;
- import com.mongodb.Mongo;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FilenameFilter;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Properties;
- import org.apache.commons.io.FileUtils;
- import org.apache.commons.io.IOUtils;
- import org.bukkit.command.CommandSender;
- import org.bukkit.entity.Player;
- import us.icebrg.imp.lang.LangCommand;
- /**
- * The "body" of the plugin, which interacts with and routes information to and
- * from the various modules.
- */
- public class IMP {
- /**
- * A string to prefix all log messages with.
- */
- public static final String logPrefix = "[IMP] ";
- /**
- * The Gson instance to use for all Gson operations. A class member so that
- * output can be standardized, i.e., always use setPrettyPrinting().
- */
- private Gson gson;
- /**
- * The MongoDB connection we are using to store all of our data.
- */
- private Mongo mongo;
- /**
- * The database in which we are storing everything.
- */
- private DB db;
- /**
- * Configuration for virtually every aspect.
- */
- private IMPConfiguration config;
- /**
- * The keys are ISO 693-3 language codes and the values are Properties files
- * containing i18n strings.
- * @see #getMessage(java.lang.String, java.lang.String) The primary method
- * of accessing this data.
- */
- private HashMap<String, Properties> languages
- = new HashMap<String, Properties>();
- /**********
- * Bukkit *
- **********/
- /**
- * The Bukkit plugin object through which we interact and respond to the
- * Bukkit server.
- */
- private IMPPlugin plugin;
- /******************
- * Sub-components *
- ******************/
- /**
- * A list of all of the top-level commands that are registered, expected to
- * be the root commands of the various modules.
- */
- private List<IMPCommand> commands = new ArrayList<IMPCommand>();
- /**
- * The active Chat module instance.
- */
- private ChatModule chat;
- /**
- * The active Government module instance.
- */
- private GovernmentModule government;
- /**
- * The active Transportation module instance.
- */
- private Transportation transportation;
- /**
- * Constructs a new IMP instance and binds it to the given IMPPlugin.
- * @param plugin the IMPPlugin instance the new instance should interact
- * with.
- */
- public IMP(IMPPlugin plugin) {
- this.plugin = plugin;
- // Set pretty printing to make the outputted JSON human-readable
- this.gson = new GsonBuilder().setPrettyPrinting().create();
- }
- /**
- * Attempts to initialize the configuration, the i18n messages, and the
- * database, logging to the Logger of this instance's IMPPlugin on error.
- * @return True on success, false on failure.
- */
- public boolean init() {
- // Clear all of the previously registered commands (they're about to be
- // re-registered)
- this.commands.clear();
- // Instantiate all of the modules.
- this.chat = new ChatModule(this);
- this.government = new GovernmentModule(this);
- this.transportation = new Transportation(this);
- // Try to load configuration.
- if ( ! ConfigurationService.loadConfigurations(this)) {
- return false;
- }
- // Try to load messages
- if ( ! this.loadMessages()) {
- return false;
- }
- // Try to load the database
- if ( ! this.loadDatabase()) {
- return false;
- }
- // Call the initializers for the various modules
- if ( ! (this.chat.init()
- && this.government.init()
- && this.transportation.init())) {
- this.log(Level.SEVERE, "One or more modules failed to initialize!");
- return false;
- }
- // Add the /imp lang commands
- new LangCommand().register(this);
- return true;
- }
- /**
- * Attempts to load all of the i18n .properties files, logging to this
- * instance's IMPPlugin's Logger on erorr.
- * @return True on success, false on failure.
- */
- private boolean loadMessages() {
- // Try to load up all of the messages file
- File messagesDir = new File(this.plugin.getDataFolder(), this.config.messagesDir);
- // Create the default messages if they don't exist
- if ( ! messagesDir.isDirectory()) {
- this.log(Level.INFO,
- "The messagesDir did not exist - creating a new default one.");
- if ( ! messagesDir.mkdir()) {
- this.log(Level.SEVERE,
- "Failed to create the messagesDir!");
- return false;
- }
- // Directory created successfuly, create the default English file
- InputStream stream =
- this.getClass().getResourceAsStream("/resources/eng.properties");
- try {
- FileUtils.writeStringToFile(
- new File(messagesDir, "eng.properties"),
- IOUtils.toString(stream), "utf-8");
- } catch (IOException e) {
- this.log(Level.SEVERE,
- "Failed to create default 'eng.properties' file!",
- e);
- return false;
- }
- }
- // Get all files ending with .properties
- File[] files = messagesDir.listFiles(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return name.endsWith(".properties");
- }
- });
- // Load all of the files into Properties intsances and store those in
- // this.languages
- try {
- for (File file : files) {
- Properties properties = new Properties();
- properties.load(new FileInputStream(file));
- // Store the Properties file in the languages array as the
- // part before the .messages suffix
- this.languages.put(
- file.getName().substring(0, 3),
- properties);
- }
- } catch (IOException e) {
- this.log(Level.SEVERE,
- "An error occurred while trying to read .messages files.",
- e);
- return false;
- }
- return true;
- }
- /**
- * Attempts to connect to and load the MongoDB database, logging to this
- * instance's IMPPlugin's Logger on erorr.
- * @return True on success, false on failure.
- */
- private boolean loadDatabase() {
- // Try to load the database.
- try {
- this.mongo = new Mongo(this.config.databaseHost, this.config.databasePort);
- this.db = this.mongo.getDB(this.config.databaseName);
- } catch (Exception e) {
- this.log(Level.SEVERE,
- "Failed to load database.", e);
- return false;
- }
- return true;
- }
- /**
- * Attempts to find an execute the appropriate IMPCommand based on the given
- * data. Shows internationalized usage information on failure.
- * @param sender The entity that sent this command.
- * @param raw The raw command string.
- * @param parts The command string separated by spaces and excluding the
- * head (/imp or /!)
- */
- public void executeCommand(CommandSender sender, String raw, String[] parts) {
- // If there was a command other than the root command, a subcommand was
- // called - show usage for it
- if (parts.length > 0) {
- // Loop through all of the registered commands, attempting to find one
- // that matches
- for (IMPCommand command : this.commands) {
- IMPCommand.SearchResult match = command.search(
- sender, raw, parts, new String[0]);
- // If we got a match
- if (match != null) {
- boolean result = match.getCommand().execute(match.getUserCommand());
- // If true was returned, execution was successful
- if (result == true) {
- return;
- }
- // If the sender is a Player and doesn't have op, only show them
- // commands which don't require op
- if (sender instanceof Player && ! ((Player)sender).isOp()) {
- this.sendUsage(
- sender,
- match.getCommand().getUsageMessageKey(),
- match.getCommand().getChildren(false));
- } else {
- this.sendUsage(
- sender,
- match.getCommand().getUsageMessageKey(),
- match.getCommand().getChildren());
- }
- return;
- }
- }
- }
- // If nothing has successfully executed
- this.sendUsage(
- sender,
- "core.usage",
- this.commands);
- }
- /**
- * An overloaded version that converts an array of subcommands into a list.
- * @see #sendUsage(org.bukkit.command.CommandSender, java.lang.String, java.util.List)
- * for the worker method.
- * @param target
- * @param usageMessageKey
- * @param subcommands
- */
- public void sendUsage(CommandSender target, String usageMessageKey,
- IMPCommand[] subcommands) {
- this.sendUsage(target, usageMessageKey, Arrays.asList(subcommands));
- }
- /**
- * Sends usage information to the given target, automatically determining
- * which localized version(s) of the usage string(s) to send.
- * @param target The CommandSender to send the usage information to.
- * @param usageMessageKey The key (corresponding to a key in a file in the
- * messages directory) whose value to look up, based on the target's
- * stored language (in the database).
- * @param subcommands A List of all of the subcommands this command.
- * possesses, if any, whose name, alias and usage information will also be
- * displayed.
- */
- public void sendUsage(CommandSender target, String usageMessageKey,
- List<IMPCommand> subcommands) {
- target.sendMessage(this.getMessage(target, usageMessageKey));
- // If there are any subcommands, output them in a list.
- if ( ! subcommands.isEmpty()) {
- target.sendMessage(this.getMessage(target, "core.subcommands"));
- for (IMPCommand child : subcommands) {
- target.sendMessage(child.getName() + " "
- + child.getAlias() + " "
- + this.getMessage(
- target, child.getUsageMessageKey()));
- }
- }
- }
- /**
- * Logs a message using this instance's IMPPlugin's Logger.
- * @param level The logging level.
- * @param message The message to log.
- */
- public void log(Level level, String message) {
- this.plugin.log(level, message);
- }
- /**
- * Logs a message using this instance's IMPPlugin's Logger, printing a
- * stacktrace of the provided Exception
- * @param level The logging level.
- * @param message The message to log.
- * @param e The exception to print a stacktrace off.
- */
- public void log(Level level, String message, Exception e) {
- this.plugin.log(level, message, e);
- }
- /**
- * Registers a top-level IMPCommand.
- * @param command The command to register.
- * @return This instance, for method chaining.
- */
- public IMP addCommand(IMPCommand command) {
- this.commands.add(command);
- return this;
- }
- /**
- * Removes a top-level IMPCommand.
- * @param command The command to remove.
- * @return This instance, for method chaining.
- */
- public IMP removeCommand(IMPCommand command) {
- this.commands.remove(command);
- return this;
- }
- /**
- *
- * @return The active configuration instance.
- */
- public IMPConfiguration getConfig() {
- return this.config;
- }
- /**
- * @param config The new IMPConfiguration to use.
- */
- public void setConfig(IMPConfiguration config) {
- this.config = config;
- }
- /**
- *
- * @return The active Gson instance, recommended for all JSON output by
- * the IMP.
- */
- public Gson getGson() {
- return this.gson;
- }
- /**
- *
- * @return The active Chat module instance.
- */
- public ChatModule getChat() {
- return this.chat;
- }
- /**
- *
- * @return The active Government module instance.
- */
- public GovernmentModule getGovernment() {
- return this.government;
- }
- /**
- *
- * @return The active Transportation module instance.
- */
- public Transportation getTransportation() {
- return this.transportation;
- }
- /**
- *
- * @param language The language to look up the key in.
- * @param key The key to look up.
- * @return The provided language's version of the message with the given
- * key, or null if none is available.
- */
- public String getMessage(String language, String key) {
- Properties properties = this.languages.get(language);
- if (language == null) {
- return null;
- }
- return properties.getProperty(key);
- }
- /**
- * A wrapper for #getMessage(String language, String key) that gets the
- * sender's preferred language from the database (defaulting to the
- * defaultLanguage in the configuration) and uses that as the language.
- * @param sender The CommandSender whose language to look up in the
- * database.
- * @param key The key to look up.
- * @return The proper localized version of the message with the given key,
- * or null if none is found.
- */
- public String getMessage(CommandSender sender, String key) {
- String name;
- String language;
- List<User> result;
- if (sender instanceof Player) {
- name = ((Player)sender).getName();
- } else {
- name = User.consoleName;
- }
- User user = new User.HavingProperties(
- this.getCollection(User.getCollectionName()),
- name).load();
- if (user != null) {
- language = user.getLanguage();
- } else {
- language = this.config.defaultLanguage;
- }
- if ( ! this.languages.containsKey(language)) {
- throw new IndexOutOfBoundsException(
- "The language the user has set is not available!");
- }
- return this.getMessage(language, key);
- }
- /**
- *
- * @return This instance's IMPPlugin.
- */
- public IMPPlugin getPlugin() {
- return this.plugin;
- }
- public HashMap<String, Properties> getLanguages() {
- return this.languages;
- }
- public Properties getLanguage(String name) {
- return this.languages.get(name);
- }
- public DBCollection getCollection(String name) {
- return this.db.getCollection(name);
- }
- }