diff options
author | KHobbits <rob@khobbits.co.uk> | 2013-08-31 23:01:47 +0100 |
---|---|---|
committer | KHobbits <rob@khobbits.co.uk> | 2013-08-31 23:11:08 +0100 |
commit | 36c61eaa06620d3d5c8daa660de290891f808c8d (patch) | |
tree | c75f5ce66f826091e440f84e6e3a90faba5e2418 | |
parent | 9908eb0619f43a578a0bf496d6f201da7ebcc1a5 (diff) | |
download | Essentials-36c61eaa06620d3d5c8daa660de290891f808c8d.tar Essentials-36c61eaa06620d3d5c8daa660de290891f808c8d.tar.gz Essentials-36c61eaa06620d3d5c8daa660de290891f808c8d.tar.lz Essentials-36c61eaa06620d3d5c8daa660de290891f808c8d.tar.xz Essentials-36c61eaa06620d3d5c8daa660de290891f808c8d.zip |
New enum cached, lazy generated KeywordReplacer
This runs before the pager, so keywords on other pages will still be parsed.
-rw-r--r-- | Essentials/src/com/earth2me/essentials/textreader/KeywordReplacer.java | 399 |
1 files changed, 280 insertions, 119 deletions
diff --git a/Essentials/src/com/earth2me/essentials/textreader/KeywordReplacer.java b/Essentials/src/com/earth2me/essentials/textreader/KeywordReplacer.java index b77b5c45e..448ceb5ba 100644 --- a/Essentials/src/com/earth2me/essentials/textreader/KeywordReplacer.java +++ b/Essentials/src/com/earth2me/essentials/textreader/KeywordReplacer.java @@ -20,8 +20,13 @@ import org.bukkit.plugin.Plugin; import static com.earth2me.essentials.I18n._; import com.earth2me.essentials.PlayerList; -import static com.earth2me.essentials.PlayerList.getMergedList; +import static com.earth2me.essentials.textreader.KeywordType.DISPLAYNAME; +import static com.earth2me.essentials.textreader.KeywordType.PLAYER; +import java.util.EnumMap; +import java.util.HashMap; import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class KeywordReplacer implements IText @@ -31,6 +36,9 @@ public class KeywordReplacer implements IText private final transient IEssentials ess; private final transient boolean extended; private transient ExecuteTimer execTimer; + private final static Pattern KEYWORD = Pattern.compile("\\{([^\\{\\}]+)\\}"); + private final static Pattern KEYWORDSPLIT = Pattern.compile("\\:"); + private final EnumMap<KeywordType, Object> keywordCache = new EnumMap<KeywordType, Object>(KeywordType.class); public KeywordReplacer(final IText input, final CommandSender sender, final IEssentials ess) { @@ -52,161 +60,269 @@ public class KeywordReplacer implements IText private void replaceKeywords(final CommandSender sender) { - String displayName, ipAddress, balance, mails, world; - String worlds, online, unique, onlineList, date, time; - String worldTime12, worldTime24, worldDate, plugins; - String userName, version, address, tps, uptime; - String coords; execTimer = new ExecuteTimer(); execTimer.start(); + User user = null; if (sender instanceof Player) { - final User user = ess.getUser(sender); + user = ess.getUser(sender); + //This is just so any displayname lookups below show the correct nickname user.setDisplayNick(); - displayName = user.getDisplayName(); - ipAddress = user.getAddress() == null || user.getAddress().getAddress() == null ? "" : user.getAddress().getAddress().toString(); - address = user.getAddress() == null ? "" : user.getAddress().toString(); - execTimer.mark("User Grab"); - balance = NumberUtil.displayCurrency(user.getMoney(), ess); - execTimer.mark("Economy"); - mails = Integer.toString(user.getMails().size()); - final Location location = user.getLocation(); - world = location == null || location.getWorld() == null ? "" : location.getWorld().getName(); - worldTime12 = DescParseTickFormat.format12(user.getWorld() == null ? 0 : user.getWorld().getTime()); - worldTime24 = DescParseTickFormat.format24(user.getWorld() == null ? 0 : user.getWorld().getTime()); - worldDate = DateFormat.getDateInstance(DateFormat.MEDIUM, ess.getI18n().getCurrentLocale()).format(DescParseTickFormat.ticksToDate(user.getWorld() == null ? 0 : user.getWorld().getFullTime())); - coords = _("coordsKeyword", location.getBlockX(), location.getBlockY(), location.getBlockZ()); } - else - { - displayName = address = ipAddress = balance = mails = world = worldTime12 = worldTime24 = worldDate = coords = ""; - } - execTimer.mark("Player variables"); - Map<String, List<User>> playerList = PlayerList.getPlayerLists(ess, extended); + execTimer.mark("User Grab"); - userName = sender.getName(); - int playerHidden = 0; - for (Player p : ess.getServer().getOnlinePlayers()) + for (int i = 0; i < input.getLines().size(); i++) { - if (ess.getUser(p).isHidden()) + String line = input.getLines().get(i); + final Matcher matcher = KEYWORD.matcher(line); + + while (matcher.find()) { - playerHidden++; + final String fullMatch = matcher.group(0); + final String keywordMatch = matcher.group(1); + final String[] matchTokens = KEYWORDSPLIT.split(keywordMatch); + line = replaceLine(line, fullMatch, matchTokens, user); } + replaced.add(line); } - online = Integer.toString(ess.getServer().getOnlinePlayers().length - playerHidden); - unique = Integer.toString(ess.getUserMap().getUniqueUsers()); - execTimer.mark("Player list"); - final StringBuilder worldsBuilder = new StringBuilder(); - for (World w : ess.getServer().getWorlds()) + execTimer.mark("Text Replace"); + final String timeroutput = execTimer.end(); + if (ess.getSettings().isDebug()) { - if (worldsBuilder.length() > 0) - { - worldsBuilder.append(", "); - } - worldsBuilder.append(w.getName()); + ess.getLogger().log(Level.INFO, "Keyword Replacer " + timeroutput); } - worlds = worldsBuilder.toString(); + } - final StringBuilder playerlistBuilder = new StringBuilder(); - for (Player p : ess.getServer().getOnlinePlayers()) + private String replaceLine(String line, final String fullMatch, final String[] matchTokens, final User user) + { + final String keyword = matchTokens[0]; + try { - if (ess.getUser(p).isHidden()) + String replacer = null; + KeywordType validKeyword = KeywordType.valueOf(keyword); + if (validKeyword.getType().equals(KeywordCachable.CACHEABLE) && keywordCache.containsKey(validKeyword)) { - continue; + replacer = keywordCache.get(validKeyword).toString(); } - if (playerlistBuilder.length() > 0) + else if (validKeyword.getType().equals(KeywordCachable.SUBVALUE)) { - playerlistBuilder.append(", "); - } - playerlistBuilder.append(p.getDisplayName()); - } - onlineList = playerlistBuilder.toString(); + String subKeyword = ""; + if (matchTokens.length > 1) + { + subKeyword = matchTokens[1]; + } - final StringBuilder pluginlistBuilder = new StringBuilder(); - for (Plugin p : ess.getServer().getPluginManager().getPlugins()) - { - if (pluginlistBuilder.length() > 0) - { - pluginlistBuilder.append(", "); + if (keywordCache.containsKey(validKeyword)) + { + Map<String, String> values = (Map<String, String>)keywordCache.get(validKeyword); + if (values.containsKey(subKeyword)) + { + replacer = values.get(subKeyword); + } + } } - pluginlistBuilder.append(p.getDescription().getName()); - } - plugins = pluginlistBuilder.toString(); - - execTimer.mark("List builders"); - - date = DateFormat.getDateInstance(DateFormat.MEDIUM, ess.getI18n().getCurrentLocale()).format(new Date()); - time = DateFormat.getTimeInstance(DateFormat.MEDIUM, ess.getI18n().getCurrentLocale()).format(new Date()); - version = ess.getServer().getVersion(); - - tps = Double.toString(ess.getTimer().getAverageTPS()); - uptime = DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime()); - - execTimer.mark("Server Dates"); + if (replacer == null) + { + replacer = ""; + switch (validKeyword) + { + case PLAYER: + case DISPLAYNAME: + if (user != null) + { + replacer = user.getDisplayName(); + } + break; + case USERNAME: + if (user != null) + { + replacer = user.getName(); + } + break; + case BALANCE: + if (user != null) + { + replacer = NumberUtil.displayCurrency(user.getMoney(), ess); + } + break; + case MAILS: + if (user != null) + { + replacer = Integer.toString(user.getMails().size()); + } + break; + case WORLD: + if (user != null) + { + final Location location = user.getLocation(); + replacer = location == null || location.getWorld() == null ? "" : location.getWorld().getName(); + } + break; + case ONLINE: + int playerHidden = 0; + for (Player p : ess.getServer().getOnlinePlayers()) + { + if (ess.getUser(p).isHidden()) + { + playerHidden++; + } + } + replacer = Integer.toString(ess.getServer().getOnlinePlayers().length - playerHidden); + break; + case UNIQUE: + replacer = Integer.toString(ess.getUserMap().getUniqueUsers()); + break; + case WORLDS: + final StringBuilder worldsBuilder = new StringBuilder(); + for (World w : ess.getServer().getWorlds()) + { + if (worldsBuilder.length() > 0) + { + worldsBuilder.append(", "); + } + worldsBuilder.append(w.getName()); + } + replacer = worldsBuilder.toString(); + break; + case PLAYERLIST: + final Map<String, String> outputList; + if (keywordCache.containsKey(validKeyword)) + { + outputList = (Map<String, String>)keywordCache.get(validKeyword); + } + else + { + //First lets build the per group playerlist + final Map<String, List<User>> playerList = PlayerList.getPlayerLists(ess, extended); + outputList = new HashMap<String, String>(); + for (String groupName : playerList.keySet()) + { + final List<User> groupUsers = playerList.get(groupName); + if (groupUsers != null && !groupUsers.isEmpty()) + { + outputList.put(groupName, PlayerList.listUsers(ess, groupUsers, " ")); + } + } - for (int i = 0; i < input.getLines().size(); i++) - { - String line = input.getLines().get(i); + //Now lets build the all user playerlist + final StringBuilder playerlistBuilder = new StringBuilder(); + for (Player p : ess.getServer().getOnlinePlayers()) + { + if (ess.getUser(p).isHidden()) + { + continue; + } + if (playerlistBuilder.length() > 0) + { + playerlistBuilder.append(", "); + } + playerlistBuilder.append(p.getDisplayName()); + } + outputList.put("", playerlistBuilder.toString()); + keywordCache.put(validKeyword, outputList); + } - line = line.replace("{PLAYER}", displayName); - line = line.replace("{DISPLAYNAME}", displayName); - line = line.replace("{USERNAME}", userName); - line = line.replace("{BALANCE}", balance); - line = line.replace("{MAILS}", mails); - line = line.replace("{WORLD}", world); - line = line.replace("{ONLINE}", online); - line = line.replace("{UNIQUE}", unique); - line = line.replace("{WORLDS}", worlds); - line = line.replace("{PLAYERLIST}", onlineList); - line = line.replace("{TIME}", time); - line = line.replace("{DATE}", date); - line = line.replace("{WORLDTIME12}", worldTime12); - line = line.replace("{WORLDTIME24}", worldTime24); - line = line.replace("{WORLDDATE}", worldDate); - line = line.replace("{COORDS}", coords); - line = line.replace("{TPS}", tps); - line = line.replace("{UPTIME}", uptime); - - if (extended) - { - line = line.replace("{IP}", ipAddress); - line = line.replace("{ADDRESS}", address); - line = line.replace("{PLUGINS}", plugins); - line = line.replace("{VERSION}", version); + //Now thats all done, output the one we want and cache the rest. + if (matchTokens.length == 1) + { + replacer = outputList.get(""); + } + else if (outputList.containsKey(matchTokens[1])) + { + replacer = outputList.get(matchTokens[1]); + } + else if (matchTokens.length > 2) + { + replacer = matchTokens[2]; + } - for (String groupName : playerList.keySet()) - { - final List<User> groupUsers = playerList.get(groupName); - if (groupUsers != null && !groupUsers.isEmpty()) + keywordCache.put(validKeyword, outputList); + break; + case TIME: + replacer = DateFormat.getTimeInstance(DateFormat.MEDIUM, ess.getI18n().getCurrentLocale()).format(new Date()); + break; + case DATE: + replacer = DateFormat.getDateInstance(DateFormat.MEDIUM, ess.getI18n().getCurrentLocale()).format(new Date()); + break; + case WORLDTIME12: + if (user != null) + { + replacer = DescParseTickFormat.format12(user.getWorld() == null ? 0 : user.getWorld().getTime()); + } + break; + case WORLDTIME24: + if (user != null) + { + replacer = DescParseTickFormat.format24(user.getWorld() == null ? 0 : user.getWorld().getTime()); + } + break; + case WORLDDATE: + if (user != null) + { + replacer = DateFormat.getDateInstance(DateFormat.MEDIUM, ess.getI18n().getCurrentLocale()).format(DescParseTickFormat.ticksToDate(user.getWorld() == null ? 0 : user.getWorld().getFullTime())); + } + break; + case COORDS: + if (user != null) + { + final Location location = user.getLocation(); + replacer = _("coordsKeyword", location.getBlockX(), location.getBlockY(), location.getBlockZ()); + } + break; + case TPS: + replacer = NumberUtil.formatDouble(ess.getTimer().getAverageTPS()); + break; + case UPTIME: + replacer = DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime()); + break; + case IP: + if (user != null) { - line = line.replaceAll("\\{PLAYERLIST\\:" + groupName.toUpperCase() + "(?:\\:([^\\{\\}]*))?\\}", - PlayerList.listUsers(ess, groupUsers, " ")); + replacer = user.getAddress() == null || user.getAddress().getAddress() == null ? "" : user.getAddress().getAddress().toString(); } + break; + case ADDRESS: + if (user != null) + { + replacer = user.getAddress() == null ? "" : user.getAddress().toString(); + } + break; + case PLUGINS: + final StringBuilder pluginlistBuilder = new StringBuilder(); + for (Plugin p : ess.getServer().getPluginManager().getPlugins()) + { + if (pluginlistBuilder.length() > 0) + { + pluginlistBuilder.append(", "); + } + pluginlistBuilder.append(p.getDescription().getName()); + } + replacer = pluginlistBuilder.toString(); + break; + case VERSION: + replacer = ess.getServer().getVersion(); + break; + default: + replacer = "N/A"; + break; } - boolean doReplace = true; - while (doReplace) + //If this is just a regular keyword, lets throw it into the cache + if (validKeyword.getType().equals(KeywordCachable.CACHEABLE)) { - final String newLine = line.replaceAll("\\{PLAYERLIST\\:\\w*(?:\\:([^\\{\\}]*))?\\}", "$1"); - if (newLine.equals(line)) - { - doReplace = false; - } - line = newLine; + keywordCache.put(validKeyword, replacer); } } - replaced.add(line); + line = line.replace(fullMatch, replacer); } - execTimer.mark("String replace"); - final String timeroutput = execTimer.end(); - if (ess.getSettings().isDebug()) + catch (IllegalArgumentException ex) { - ess.getLogger().log(Level.INFO, "Keyword Replacer " + timeroutput); } + return line; } @Override @@ -227,3 +343,48 @@ public class KeywordReplacer implements IText return input.getBookmarks(); } } + +//When adding a keyword here, you also need to add the implementation above +enum KeywordType +{ + PLAYER(KeywordCachable.CACHEABLE), + DISPLAYNAME(KeywordCachable.CACHEABLE), + USERNAME(KeywordCachable.NOTCACHEABLE), + BALANCE(KeywordCachable.CACHEABLE), + MAILS(KeywordCachable.CACHEABLE), + WORLD(KeywordCachable.CACHEABLE), + ONLINE(KeywordCachable.CACHEABLE), + UNIQUE(KeywordCachable.CACHEABLE), + WORLDS(KeywordCachable.CACHEABLE), + PLAYERLIST(KeywordCachable.SUBVALUE), + TIME(KeywordCachable.CACHEABLE), + DATE(KeywordCachable.CACHEABLE), + WORLDTIME12(KeywordCachable.CACHEABLE), + WORLDTIME24(KeywordCachable.CACHEABLE), + WORLDDATE(KeywordCachable.CACHEABLE), + COORDS(KeywordCachable.CACHEABLE), + TPS(KeywordCachable.CACHEABLE), + UPTIME(KeywordCachable.CACHEABLE), + IP(KeywordCachable.CACHEABLE), + ADDRESS(KeywordCachable.CACHEABLE), + PLUGINS(KeywordCachable.CACHEABLE), + VERSION(KeywordCachable.CACHEABLE); + private final KeywordCachable type; + + KeywordType(KeywordCachable type) + { + this.type = type; + } + + public KeywordCachable getType() + { + return type; + } +} + +enum KeywordCachable +{ + CACHEABLE, // This keyword can be cached as a string + SUBVALUE, // This keyword can be cached as a map + NOTCACHEABLE; // This keyword should never be cached +}
\ No newline at end of file |