diff --git a/src/main/java/me/clip/placeholderapi/PlaceholderAPI.java b/src/main/java/me/clip/placeholderapi/PlaceholderAPI.java index 648963a..7da56a6 100644 --- a/src/main/java/me/clip/placeholderapi/PlaceholderAPI.java +++ b/src/main/java/me/clip/placeholderapi/PlaceholderAPI.java @@ -20,8 +20,18 @@ */ package me.clip.placeholderapi; +import static me.clip.placeholderapi.util.Msg.color; + import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import me.clip.placeholderapi.events.ExpansionRegisterEvent; import me.clip.placeholderapi.events.ExpansionUnregisterEvent; import me.clip.placeholderapi.expansion.PlaceholderExpansion; @@ -32,309 +42,332 @@ import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import static me.clip.placeholderapi.util.Msg.color; - public class PlaceholderAPI { - private PlaceholderAPI() { + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("[%]([^%]+)[%]"); + private static final Pattern BRACKET_PLACEHOLDER_PATTERN = Pattern.compile("[{]([^{}]+)[}]"); + private static final Pattern RELATIONAL_PLACEHOLDER_PATTERN = Pattern.compile("[%](rel_)([^%]+)[%]"); + private static final Map placeholders = new HashMap<>(); + private PlaceholderAPI() { + } + + /** + * check if a specific placeholder identifier is currently registered + * + * @param identifier to check + * @return true if identifier is already registered + */ + public static boolean isRegistered(String identifier) { + return getRegisteredIdentifiers().stream().filter(id -> id.equalsIgnoreCase(identifier)) + .findFirst().orElse(null) != null; + } + + /** + * Register a new placeholder hook + * + * @param identifier Identifier of the placeholder -> "%(identifier)_(args...)% + * @param placeholderHook implementing class that contains the onPlaceholderRequest method which + * is called when a value is needed for the specific placeholder + * @return true if the hook was successfully registered, false if there is already a hook + * registered for the specified identifier + */ + public static boolean registerPlaceholderHook(String identifier, + PlaceholderHook placeholderHook) { + Validate.notNull(identifier, "Identifier can not be null"); + Validate.notNull(placeholderHook, "Placeholderhook can not be null"); + if (isRegistered(identifier)) { + return false; } + placeholders.put(identifier.toLowerCase(), placeholderHook); + return true; + } - private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("[%]([^%]+)[%]"); - private static final Pattern BRACKET_PLACEHOLDER_PATTERN = Pattern.compile("[{]([^{}]+)[}]"); - private static final Pattern RELATIONAL_PLACEHOLDER_PATTERN = Pattern.compile("[%](rel_)([^%]+)[%]"); - private static final Map placeholders = new HashMap<>(); + /** + * unregister a placeholder hook by identifier + * + * @param identifier the identifier for the placeholder hook to unregister + * @return true if the placeholder hook was successfully unregistered, false if there was no + * placeholder hook registered for the identifier specified + */ + public static boolean unregisterPlaceholderHook(String identifier) { + Validate.notNull(identifier, "Identifier can not be null"); + return placeholders.remove(identifier.toLowerCase()) != null; + } - /** - * check if a specific placeholder identifier is currently registered - * - * @param identifier to check - * @return true if identifier is already registered - */ - public static boolean isRegistered(String identifier) { - return getRegisteredIdentifiers().stream().filter(id -> id.equalsIgnoreCase(identifier)).findFirst().orElse(null) != null; + /** + * Get all registered placeholder identifiers + * + * @return all registered placeholder identifiers + */ + public static Set getRegisteredIdentifiers() { + return ImmutableSet.copyOf(placeholders.keySet()); + } + + /** + * Get map of registered placeholders + * + * @return copy of the internal placeholder map + */ + public static Map getPlaceholders() { + return ImmutableMap.copyOf(placeholders); + } + + public static Set getExpansions() { + Set set = getPlaceholders().values().stream() + .filter(PlaceholderExpansion.class::isInstance).map(PlaceholderExpansion.class::cast) + .collect(Collectors.toCollection(HashSet::new)); + return ImmutableSet.copyOf(set); + } + + /** + * check if a String contains any PlaceholderAPI placeholders + * + * @param text String to check + * @return true if String contains any registered placeholder identifiers, false otherwise + */ + public static boolean containsPlaceholders(String text) { + return text != null && PLACEHOLDER_PATTERN.matcher(text).find(); + } + + /** + * check if a String contains any PlaceholderAPI bracket placeholders + * + * @param text String to check + * @return true if String contains any registered placeholder identifiers, false otherwise + */ + public static boolean containsBracketPlaceholders(String text) { + return text != null && BRACKET_PLACEHOLDER_PATTERN.matcher(text).find(); + } + + /** + * set placeholders in the list text provided placeholders are matched with the pattern + * {} when set with this method + * + * @param p Player to parse the placeholders for + * @param text text to set the placeholder values in + * @return modified list with all placeholders set to the corresponding values + */ + public static List setBracketPlaceholders(OfflinePlayer p, List text) { + return setPlaceholders(p, text, BRACKET_PLACEHOLDER_PATTERN); + } + + /** + * set placeholders in the list text provided placeholders are matched with the pattern + * %(identifier)_(params)>% when set with this method + * + * @param p Player to parse the placeholders for + * @param text text to parse the placeholder values in + * @return modified list with all placeholders set to the corresponding values + */ + public static List setPlaceholders(OfflinePlayer p, List text) { + return setPlaceholders(p, text, PLACEHOLDER_PATTERN); + } + + /** + * set placeholders in the list text provided placeholders are matched with the pattern + * %(identifier)_(params)>% when set with this method + * + * @param p Player to parse the placeholders for + * @param text text to parse the placeholder values in + * @return modified list with all placeholders set to the corresponding values + */ + public static List setPlaceholders(OfflinePlayer p, List text, Pattern pattern) { + if (text == null) { + return null; } + return text.stream().map(line -> setPlaceholders(p, line, pattern)) + .collect(Collectors.toList()); + } - /** - * Register a new placeholder hook - * - * @param identifier Identifier of the placeholder -> "%(identifier)_(args...)% - * @param placeholderHook implementing class that contains the onPlaceholderRequest method which is called when a value is needed for the specific placeholder - * @return true if the hook was successfully registered, false if there is already a hook registered for the specified identifier - */ - public static boolean registerPlaceholderHook(String identifier, PlaceholderHook placeholderHook) { - Validate.notNull(identifier, "Identifier can not be null"); - Validate.notNull(placeholderHook, "Placeholderhook can not be null"); - if (isRegistered(identifier)) return false; - placeholders.put(identifier.toLowerCase(), placeholderHook); - return true; + /** + * set placeholders in the text specified placeholders are matched with the pattern + * {} when set with this method + * + * @param player Player to parse the placeholders for + * @param text text to parse the placeholder values to + * @return modified text with all placeholders set to the corresponding values + */ + public static String setBracketPlaceholders(OfflinePlayer player, String text) { + return setPlaceholders(player, text, BRACKET_PLACEHOLDER_PATTERN); + } + + /** + * set placeholders in the text specified placeholders are matched with the pattern + * %<(identifier)_(params)>% when set with this method + * + * @param player Player to parse the placeholders for + * @param text text to parse the placeholder values to + * @return text with all placeholders set to the corresponding values + */ + public static String setPlaceholders(OfflinePlayer player, String text) { + return setPlaceholders(player, text, PLACEHOLDER_PATTERN); + } + + /** + * set placeholders in the text specified placeholders are matched with the pattern + * %<(identifier)_(params)>% when set with this method + * + * @param player Player to parse the placeholders for + * @param text text to parse the placeholder values to + * @param placeholderPattern the pattern to match placeholders to. Capture group 1 must contain an + * underscore separating the identifier from the params + * @return text with all placeholders set to the corresponding values + */ + public static String setPlaceholders(OfflinePlayer player, String text, + Pattern placeholderPattern) { + if (text == null) { + return null; } - - /** - * unregister a placeholder hook by identifier - * - * @param identifier the identifier for the placeholder hook to unregister - * @return true if the placeholder hook was successfully unregistered, false if there was no placeholder hook registered for the identifier specified - */ - public static boolean unregisterPlaceholderHook(String identifier) { - Validate.notNull(identifier, "Identifier can not be null"); - return placeholders.remove(identifier.toLowerCase()) != null; + if (placeholders.isEmpty()) { + return color(text); } - - /** - * Get all registered placeholder identifiers - * - * @return all registered placeholder identifiers - */ - public static Set getRegisteredIdentifiers() { - return ImmutableSet.copyOf(placeholders.keySet()); - } - - /** - * Get map of registered placeholders - * - * @return copy of the internal placeholder map - */ - public static Map getPlaceholders() { - return ImmutableMap.copyOf(placeholders); - } - - public static Set getExpansions() { - Set set = getPlaceholders().values().stream().filter(PlaceholderExpansion.class::isInstance).map(PlaceholderExpansion.class::cast).collect(Collectors.toCollection(HashSet::new)); - return ImmutableSet.copyOf(set); - } - - /** - * check if a String contains any PlaceholderAPI placeholders - * - * @param text String to check - * @return true if String contains any registered placeholder identifiers, false otherwise - */ - public static boolean containsPlaceholders(String text) { - return text != null && PLACEHOLDER_PATTERN.matcher(text).find(); - } - - /** - * check if a String contains any PlaceholderAPI bracket placeholders - * - * @param text String to check - * @return true if String contains any registered placeholder identifiers, false otherwise - */ - public static boolean containsBracketPlaceholders(String text) { - return text != null && BRACKET_PLACEHOLDER_PATTERN.matcher(text).find(); - } - - /** - * set placeholders in the list text provided - * placeholders are matched with the pattern {} when set with this method - * - * @param p Player to parse the placeholders for - * @param text text to set the placeholder values in - * @return modified list with all placeholders set to the corresponding values - */ - public static List setBracketPlaceholders(OfflinePlayer p, List text) { - return setPlaceholders(p, text, BRACKET_PLACEHOLDER_PATTERN); - } - - /** - * set placeholders in the list text provided - * placeholders are matched with the pattern %(identifier)_(params)>% when set with this method - * - * @param p Player to parse the placeholders for - * @param text text to parse the placeholder values in - * @return modified list with all placeholders set to the corresponding values - */ - public static List setPlaceholders(OfflinePlayer p, List text) { - return setPlaceholders(p, text, PLACEHOLDER_PATTERN); - } - - /** - * set placeholders in the list text provided - * placeholders are matched with the pattern %(identifier)_(params)>% when set with this method - * - * @param p Player to parse the placeholders for - * @param text text to parse the placeholder values in - * @return modified list with all placeholders set to the corresponding values - */ - public static List setPlaceholders(OfflinePlayer p, List text, Pattern pattern) { - if (text == null) return null; - return text.stream().map(line -> setPlaceholders(p, line, pattern)).collect(Collectors.toList()); - } - - /** - * set placeholders in the text specified - * placeholders are matched with the pattern {} when set with this method - * - * @param player Player to parse the placeholders for - * @param text text to parse the placeholder values to - * @return modified text with all placeholders set to the corresponding values - */ - public static String setBracketPlaceholders(OfflinePlayer player, String text) { - return setPlaceholders(player, text, BRACKET_PLACEHOLDER_PATTERN); - } - - /** - * set placeholders in the text specified - * placeholders are matched with the pattern %<(identifier)_(params)>% when set with this method - * - * @param player Player to parse the placeholders for - * @param text text to parse the placeholder values to - * @return text with all placeholders set to the corresponding values - */ - public static String setPlaceholders(OfflinePlayer player, String text) { - return setPlaceholders(player, text, PLACEHOLDER_PATTERN); - } - - /** - * set placeholders in the text specified - * placeholders are matched with the pattern %<(identifier)_(params)>% when set with this method - * - * @param player Player to parse the placeholders for - * @param text text to parse the placeholder values to - * @param placeholderPattern the pattern to match placeholders to. Capture group 1 must contain an underscore separating the identifier from the params - * @return text with all placeholders set to the corresponding values - */ - public static String setPlaceholders(OfflinePlayer player, String text, Pattern placeholderPattern) { - if (text == null) return null; - if (placeholders.isEmpty()) return color(text); - Matcher m = placeholderPattern.matcher(text); - Map hooks = getPlaceholders(); - while (m.find()) { - String format = m.group(1); - int index = format.indexOf("_"); - if (index <= 0 || index >= format.length()) continue; - String identifier = format.substring(0, index).toLowerCase(); - String params = format.substring(index + 1); - if (hooks.containsKey(identifier)) { - String value = hooks.get(identifier).onPlaceholderRequest(player, params); - if (value != null) { - text = text.replaceAll(Pattern.quote(m.group()), Matcher.quoteReplacement(value)); - } - } + Matcher m = placeholderPattern.matcher(text); + Map hooks = getPlaceholders(); + while (m.find()) { + String format = m.group(1); + int index = format.indexOf("_"); + if (index <= 0 || index >= format.length()) { + continue; + } + String identifier = format.substring(0, index).toLowerCase(); + String params = format.substring(index + 1); + if (hooks.containsKey(identifier)) { + Object value = hooks.get(identifier).onPlaceholderRequest(player, params); + if (value != null) { + text = text.replaceAll(Pattern.quote(m.group()), Matcher.quoteReplacement(String.valueOf(value))); } - return color(text); + } } + return color(text); + } - /** - * set relational placeholders in the text specified - * placeholders are matched with the pattern %% when set with this method - * - * @param one Player to compare - * @param two Player to compare - * @param text text to parse the placeholder values to - * @return text with all relational placeholders set to the corresponding values - */ - public static List setRelationalPlaceholders(Player one, Player two, List text) { - if (text == null) return null; - return text.stream().map(line -> setRelationalPlaceholders(one, two, line)).collect(Collectors.toList()); + /** + * set relational placeholders in the text specified placeholders are matched with the pattern + * %% when set with this method + * + * @param one Player to compare + * @param two Player to compare + * @param text text to parse the placeholder values to + * @return text with all relational placeholders set to the corresponding values + */ + public static List setRelationalPlaceholders(Player one, Player two, List text) { + if (text == null) { + return null; } + return text.stream().map(line -> setRelationalPlaceholders(one, two, line)) + .collect(Collectors.toList()); + } - /** - * set relational placeholders in the text specified - * placeholders are matched with the pattern %% when set with this method - * - * @param one Player to compare - * @param two Player to compare - * @param text text to parse the placeholder values to - * @return text with all relational placeholders set to the corresponding values - */ - public static String setRelationalPlaceholders(Player one, Player two, String text) { - if (text == null) return null; - if (placeholders.isEmpty()) return color(text); - Matcher m = RELATIONAL_PLACEHOLDER_PATTERN.matcher(text); - Map hooks = getPlaceholders(); - while (m.find()) { - String format = m.group(2); - int index = format.indexOf("_"); - if (index <= 0 || index >= format.length()) continue; - String identifier = format.substring(0, index).toLowerCase(); - String params = format.substring(index + 1); - if (hooks.containsKey(identifier)) { - if (!(hooks.get(identifier) instanceof Relational)) { - continue; - } - Relational rel = (Relational) hooks.get(identifier); - String value = rel.onPlaceholderRequest(one, two, params); - if (value != null) { - text = text.replaceAll(Pattern.quote(m.group()), Matcher.quoteReplacement(value)); - } - } + /** + * set relational placeholders in the text specified placeholders are matched with the pattern + * %% when set with this method + * + * @param one Player to compare + * @param two Player to compare + * @param text text to parse the placeholder values to + * @return text with all relational placeholders set to the corresponding values + */ + public static String setRelationalPlaceholders(Player one, Player two, String text) { + if (text == null) { + return null; + } + if (placeholders.isEmpty()) { + return color(text); + } + Matcher m = RELATIONAL_PLACEHOLDER_PATTERN.matcher(text); + Map hooks = getPlaceholders(); + while (m.find()) { + String format = m.group(2); + int index = format.indexOf("_"); + if (index <= 0 || index >= format.length()) { + continue; + } + String identifier = format.substring(0, index).toLowerCase(); + String params = format.substring(index + 1); + if (hooks.containsKey(identifier)) { + if (!(hooks.get(identifier) instanceof Relational)) { + continue; } - return color(text); - } - - /** - * unregister ALL placeholder hooks that are currently registered - */ - protected static void unregisterAll() { - unregisterAllProvidedExpansions(); - placeholders.clear(); - } - - /** - * unregister all expansions provided by PlaceholderAPI - */ - public static void unregisterAllProvidedExpansions() { - if (placeholders.isEmpty()) return; - getPlaceholders().forEach((key, value) -> { - if (value instanceof PlaceholderExpansion) { - PlaceholderExpansion ex = (PlaceholderExpansion) value; - if (!ex.persist()) { - unregisterExpansion(ex); - } - } - }); - } - - public static boolean registerExpansion(PlaceholderExpansion ex) { - if (registerPlaceholderHook(ex.getIdentifier(), ex)) { - Bukkit.getPluginManager().callEvent(new ExpansionRegisterEvent(ex)); - return true; + Relational rel = (Relational) hooks.get(identifier); + String value = rel.onPlaceholderRequest(one, two, params); + if (value != null) { + text = text.replaceAll(Pattern.quote(m.group()), Matcher.quoteReplacement(value)); } - return false; + } } + return color(text); + } - public static boolean unregisterExpansion(PlaceholderExpansion ex) { - if (unregisterPlaceholderHook(ex.getIdentifier())) { - Bukkit.getPluginManager().callEvent(new ExpansionUnregisterEvent(ex)); - return true; + /** + * unregister ALL placeholder hooks that are currently registered + */ + protected static void unregisterAll() { + unregisterAllProvidedExpansions(); + placeholders.clear(); + } + + /** + * unregister all expansions provided by PlaceholderAPI + */ + public static void unregisterAllProvidedExpansions() { + if (placeholders.isEmpty()) { + return; + } + getPlaceholders().forEach((key, value) -> { + if (value instanceof PlaceholderExpansion) { + PlaceholderExpansion ex = (PlaceholderExpansion) value; + if (!ex.persist()) { + unregisterExpansion(ex); } - return false; - } + } + }); + } - public static Pattern getPlaceholderPattern() { - return PLACEHOLDER_PATTERN; + public static boolean registerExpansion(PlaceholderExpansion ex) { + if (registerPlaceholderHook(ex.getIdentifier(), ex)) { + Bukkit.getPluginManager().callEvent(new ExpansionRegisterEvent(ex)); + return true; } + return false; + } - public static Pattern getBracketPlaceholderPattern() { - return BRACKET_PLACEHOLDER_PATTERN; + public static boolean unregisterExpansion(PlaceholderExpansion ex) { + if (unregisterPlaceholderHook(ex.getIdentifier())) { + Bukkit.getPluginManager().callEvent(new ExpansionUnregisterEvent(ex)); + return true; } + return false; + } - public static Pattern getRelationalPlaceholderPattern() { - return RELATIONAL_PLACEHOLDER_PATTERN; - } + public static Pattern getPlaceholderPattern() { + return PLACEHOLDER_PATTERN; + } - @Deprecated - public static Set getRegisteredPlaceholderPlugins() { - return getRegisteredIdentifiers(); - } + public static Pattern getBracketPlaceholderPattern() { + return BRACKET_PLACEHOLDER_PATTERN; + } - @Deprecated - public static Set getExternalPlaceholderPlugins() { - return null; - } + public static Pattern getRelationalPlaceholderPattern() { + return RELATIONAL_PLACEHOLDER_PATTERN; + } - @Deprecated - public static boolean registerPlaceholderHook(Plugin plugin, PlaceholderHook placeholderHook) { - return plugin != null && registerPlaceholderHook(plugin.getName(), placeholderHook); - } + @Deprecated + public static Set getRegisteredPlaceholderPlugins() { + return getRegisteredIdentifiers(); + } - @Deprecated - public static boolean unregisterPlaceholderHook(Plugin plugin) { - return plugin != null && unregisterPlaceholderHook(plugin.getName()); - } + @Deprecated + public static Set getExternalPlaceholderPlugins() { + return null; + } + + @Deprecated + public static boolean registerPlaceholderHook(Plugin plugin, PlaceholderHook placeholderHook) { + return plugin != null && registerPlaceholderHook(plugin.getName(), placeholderHook); + } + + @Deprecated + public static boolean unregisterPlaceholderHook(Plugin plugin) { + return plugin != null && unregisterPlaceholderHook(plugin.getName()); + } } diff --git a/src/main/java/me/clip/placeholderapi/PlaceholderHook.java b/src/main/java/me/clip/placeholderapi/PlaceholderHook.java index 161898e..075e71f 100644 --- a/src/main/java/me/clip/placeholderapi/PlaceholderHook.java +++ b/src/main/java/me/clip/placeholderapi/PlaceholderHook.java @@ -31,7 +31,7 @@ public abstract class PlaceholderHook { * @param params String passed to the hook to determine what value to return * @return value for the requested player and params */ - public String onPlaceholderRequest(OfflinePlayer p, String params) { + public Object onPlaceholderRequest(OfflinePlayer p, String params) { if (p != null && p.isOnline()) { return onPlaceholderRequest((Player) p, params); }