Java tutorial
/* * ExperienceMod - Bukkit server plugin for modifying the experience system in Minecraft. * Copyright (C) 2012 Kristian S. Stangeland * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ package com.comphenix.xp.messages; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang.NullArgumentException; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringEscapeUtils; import org.bukkit.ChatColor; import org.bukkit.entity.Player; import com.comphenix.xp.parser.Utility; import com.comphenix.xp.rewards.ResourceHolder; public class MessageFormatter { private Player source; private Integer count; private Collection<ResourceHolder> result; private List<ResourceHolder> generated; private static Pattern parameterPattern = Pattern.compile("\\{\\w+\\}"); // Default public MessageFormatter() { setCount(1); } public MessageFormatter(Player player, Collection<ResourceHolder> result, List<ResourceHolder> generated) { this(player, result, generated, 1); } public MessageFormatter(Player player, Collection<ResourceHolder> result, List<ResourceHolder> generated, Integer count) { setSource(player); setResult(result); setGenerated(generated); setCount(count); } /** * Replaces parameters in the text with their respective value. * @param message - message to format. * @return Message with every parameter replaced with the corresponding value. */ public String formatMessage(String message) { if (message == null) return null; Map<String, ResourceHolder> lookup = getResultMapping(); StringBuffer output = new StringBuffer(); Matcher matcher = parameterPattern.matcher(message); // Simple variables // TODO: Add more variables. String sourceText = source != null ? source.getDisplayName() : "Unknown"; String countText = count != null ? count.toString() : "N/A"; while (matcher.find()) { String enumed = Utility.getEnumName(matcher.group()); // Replace parameters if (enumed.equals("PLAYER")) matcher.appendReplacement(output, sourceText); else if (enumed.equals("COUNT")) matcher.appendReplacement(output, countText); else if (lookup.containsKey(enumed)) matcher.appendReplacement(output, lookup.get(enumed).toString()); else matcher.appendReplacement(output, "{CANNOT FIND " + matcher.group() + "}"); } // Remember color matcher.appendTail(output); return formatUnescape(formatColor(output)); } private String formatColor(StringBuffer input) { // Treat ampersand as a color character return translateAlternateColorCodes('&', input.toString()); } private String formatUnescape(String input) { return StringEscapeUtils.unescapeJava(input); } // Don't translate color codes when the ampersand is escaped private static String translateAlternateColorCodes(char altColorChar, String textToTranslate) { boolean hasEscape = false; char[] b = textToTranslate.toCharArray(); // Handle Java escaping as well for (int i = 0; i < b.length - 1; i++) { if (!hasEscape && b[i] == '\\') { hasEscape = true; } else if (!hasEscape && b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) { b[i] = ChatColor.COLOR_CHAR; b[i + 1] = Character.toLowerCase(b[i + 1]); } else { hasEscape = false; } } return new String(b); } // Convert a list of resources into a Hash Table private Map<String, ResourceHolder> getResultMapping() { Map<String, ResourceHolder> lookup = new HashMap<String, ResourceHolder>(); for (ResourceHolder resource : getResult()) { lookup.put(resource.getName(), resource); } return lookup; } /** * Retrieves the number of times this message has been generated since it was last transmitted. * @return The number of outstanding messages of this type. */ public Integer getCount() { return count; } /** * Sets the number of times this message has been generated since it was last transmitted. * @param count - new count. */ public void setCount(Integer count) { this.count = count; } /** * Retrieves the player that caused this message to be sent, or NULL if it was caused by the environment. * @return The player, if any, that caused the message to be sent. */ public Player getSource() { return source; } /** * Sets the player that caused this message to be sent. * @param source - the player that caused the message, or NULl it if was the enviornment. */ public void setSource(Player source) { this.source = source; } /** * Retrieves the list of resources awarded. * @return List of resources. */ public Collection<ResourceHolder> getResult() { return result; } /** * Sets the list of resources awarded. * @param result - the new list of resources awarded. */ public void setResult(Collection<ResourceHolder> result) { this.result = result; } /** * Retrieves the list of resources generated, ordered by reward providers. * <p> * This list is the sum of all previous lists. * @return The current list. */ public List<ResourceHolder> getGenerated() { return generated; } /** * Sets the list of resources generated, ordered by reward providers. * @param generated - new list of resources. */ public void setGenerated(List<ResourceHolder> generated) { this.generated = generated; } /** * Adds every parameter in both message formatters. Note that a and b * must be non-null and have the same player source. * @param a - first message formatter to add. * @param b - second message formatter to add. * @return The resulting message formatter. */ public static MessageFormatter add(MessageFormatter a, MessageFormatter b) { if (a == null) throw new NullArgumentException("a"); if (b == null) throw new NullArgumentException("b"); // Add the two formatters return a.add(b); } /** * Adds every parameter in both message formatters, creating a new message * formatter with the results. * @param other - message formatter to add. * @return The resulting message formatter. */ public MessageFormatter add(MessageFormatter other) { if (!ObjectUtils.equals(getSource(), other.getSource())) throw new IllegalArgumentException("Message formatters for different players cannot be added."); // Add values return new MessageFormatter(getSource(), addResults(other), addGenerated(other), getInt(getCount()) + getInt(other.getCount())); } // Merge resources private Collection<ResourceHolder> addResults(MessageFormatter other) { Map<String, ResourceHolder> current = getResultMapping(); // Add every resource from other for (ResourceHolder resource : other.getResult()) { String name = resource.getName(); if (current.containsKey(name)) current.put(name, current.get(name).add(resource)); else current.put(name, resource); } return current.values(); } // Merge generated private List<ResourceHolder> addGenerated(MessageFormatter other) { List<ResourceHolder> current = new ArrayList<ResourceHolder>(getGenerated()); List<ResourceHolder> adding = other.getGenerated(); // Add each resource for (int i = 0; i < adding.size(); i++) { // Elements outside the list are treated as empty if (i < current.size()) current.set(i, current.get(i).add(adding.get(i))); else current.add(adding.get(i)); } return current; } private static int getInt(Integer value) { return value != null ? value : 0; } /** * Create a copy of the message formatter with the given parameters * @param player - the player that caused the current action. * @param result - combined resources after awarding a player. * @param generated - the generated list of resources, in the same order as the reward providers. * @return A copy of the current message formatter. */ public MessageFormatter createView(Player player, Collection<ResourceHolder> result, List<ResourceHolder> generated) { return new MessageFormatter(player, result, generated); } /** * Create a copy of the message formatter with the given parameters * @param player - the player that caused the current action. * @param result - combined resources after awarding a player. * @param generated - the generated list of resources, in the same order as the reward providers. * @param count - number of times the message has been sent. * @return A copy of the current message formatter. */ public MessageFormatter createView(Player player, Collection<ResourceHolder> result, List<ResourceHolder> generated, Integer count) { return new MessageFormatter(player, result, generated, count); } /** * Create a copy of the message formatter with the given parameters * @param result - combined resources after awarding a player. * @param generated - the generated list of resources, in the same order as the reward providers. * @return A copy of the current message formatter. */ public MessageFormatter createView(Collection<ResourceHolder> result, List<ResourceHolder> generated) { return createView(source, result, generated, count); } }