* #1026 Add more tags for forced commands (lazily replaced) - Extract lazy replacement of tags to its own class - Implement wrapper to replace a String property within an object - Use wrapper in command manager and add new tags * Make argument type generic in lazy tags util
This commit is contained in:
+8
-8
@@ -1,16 +1,16 @@
|
||||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Replaceable tag whose value depends on the player.
|
||||
* Replaceable tag whose value depends on an argument.
|
||||
*
|
||||
* @param <A> the argument type
|
||||
*/
|
||||
public class PlayerTag implements Tag {
|
||||
public class DependentTag<A> implements Tag<A> {
|
||||
|
||||
private final String name;
|
||||
private final Function<Player, String> replacementFunction;
|
||||
private final Function<A, String> replacementFunction;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -18,7 +18,7 @@ public class PlayerTag implements Tag {
|
||||
* @param name the tag (placeholder) that will be replaced
|
||||
* @param replacementFunction the function producing the replacement
|
||||
*/
|
||||
public PlayerTag(String name, Function<Player, String> replacementFunction) {
|
||||
public DependentTag(String name, Function<A, String> replacementFunction) {
|
||||
this.name = name;
|
||||
this.replacementFunction = replacementFunction;
|
||||
}
|
||||
@@ -29,7 +29,7 @@ public class PlayerTag implements Tag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(Player player) {
|
||||
return replacementFunction.apply(player);
|
||||
public String getValue(A argument) {
|
||||
return replacementFunction.apply(argument);
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Tag to be replaced that does not depend on the player.
|
||||
* Tag to be replaced that does not depend on an argument.
|
||||
*
|
||||
* @param <A> type of the argument (not used in this implementation)
|
||||
*/
|
||||
public class SimpleTag implements Tag {
|
||||
public class SimpleTag<A> implements Tag<A> {
|
||||
|
||||
private final String name;
|
||||
private final Supplier<String> replacementFunction;
|
||||
@@ -23,7 +23,7 @@ public class SimpleTag implements Tag {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(Player player) {
|
||||
public String getValue(A argument) {
|
||||
return replacementFunction.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Represents a tag in a text to be replaced with a value (which may depend on the Player).
|
||||
* Represents a tag in a text to be replaced with a value (which may depend on some argument).
|
||||
*
|
||||
* @param <A> argument type the replacement may depend on
|
||||
*/
|
||||
public interface Tag {
|
||||
public interface Tag<A> {
|
||||
|
||||
/**
|
||||
* @return the tag to replace
|
||||
@@ -13,10 +13,10 @@ public interface Tag {
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Returns the value to replace the tag with for the given player.
|
||||
* Returns the value to replace the tag with for the given argument.
|
||||
*
|
||||
* @param player the player to evaluate the replacement for
|
||||
* @param argument the argument to evaluate the replacement for
|
||||
* @return the replacement
|
||||
*/
|
||||
String getValue(Player player);
|
||||
String getValue(A argument);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -13,11 +11,11 @@ public final class TagBuilder {
|
||||
private TagBuilder() {
|
||||
}
|
||||
|
||||
public static Tag createTag(String name, Function<Player, String> replacementFunction) {
|
||||
return new PlayerTag(name, replacementFunction);
|
||||
public static <A> Tag<A> createTag(String name, Function<A, String> replacementFunction) {
|
||||
return new DependentTag<>(name, replacementFunction);
|
||||
}
|
||||
|
||||
public static Tag createTag(String name, Supplier<String> replacementFunction) {
|
||||
return new SimpleTag(name, replacementFunction);
|
||||
public static <A> Tag<A> createTag(String name, Supplier<String> replacementFunction) {
|
||||
return new SimpleTag<>(name, replacementFunction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Replaces tags lazily by first determining which tags are being used
|
||||
* and only applying those replacements afterwards.
|
||||
*
|
||||
* @param <A> the argument type
|
||||
*/
|
||||
public class TagReplacer<A> {
|
||||
|
||||
private final List<Tag<A>> tags;
|
||||
private final Collection<String> messages;
|
||||
|
||||
/**
|
||||
* Private constructor. Use {@link #newReplacer(Collection, Collection)}.
|
||||
*
|
||||
* @param tags the tags that are being used in the messages
|
||||
* @param messages the messages
|
||||
*/
|
||||
private TagReplacer(List<Tag<A>> tags, Collection<String> messages) {
|
||||
this.tags = tags;
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this class, which will provide the given
|
||||
* messages adapted with the provided tags.
|
||||
*
|
||||
* @param allTags all available tags
|
||||
* @param messages the messages to use
|
||||
* @param <A> the argument type
|
||||
* @return new tag replacer instance
|
||||
*/
|
||||
public static <A> TagReplacer<A> newReplacer(Collection<Tag<A>> allTags, Collection<String> messages) {
|
||||
List<Tag<A>> usedTags = determineUsedTags(allTags, messages);
|
||||
return new TagReplacer<>(usedTags, messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the messages with the tags applied for the given argument.
|
||||
*
|
||||
* @param argument the argument to get the messages for
|
||||
* @return the adapted messages
|
||||
*/
|
||||
public List<String> getAdaptedMessages(A argument) {
|
||||
// Note ljacqu 20170121: Using a Map might seem more natural here but we avoid doing so for performance
|
||||
// Although the performance gain here is probably minimal...
|
||||
List<TagValue> tagValues = new LinkedList<>();
|
||||
for (Tag<A> tag : tags) {
|
||||
tagValues.add(new TagValue(tag.getName(), tag.getValue(argument)));
|
||||
}
|
||||
|
||||
List<String> adaptedMessages = new LinkedList<>();
|
||||
for (String line : messages) {
|
||||
String adaptedLine = line;
|
||||
for (TagValue tagValue : tagValues) {
|
||||
adaptedLine = adaptedLine.replace(tagValue.tag, tagValue.value);
|
||||
}
|
||||
adaptedMessages.add(adaptedLine);
|
||||
}
|
||||
return adaptedMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which tags are used somewhere in the given list of messages.
|
||||
*
|
||||
* @param allTags all available tags
|
||||
* @param messages the messages
|
||||
* @param <A> argument type
|
||||
* @return tags used at least once
|
||||
*/
|
||||
private static <A> List<Tag<A>> determineUsedTags(Collection<Tag<A>> allTags, Collection<String> messages) {
|
||||
return allTags.stream()
|
||||
.filter(tag -> messages.stream().anyMatch(msg -> msg.contains(tag.getName())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/** (Tag, value) pair. */
|
||||
private static final class TagValue {
|
||||
|
||||
/** The tag to replace. */
|
||||
private final String tag;
|
||||
/** The value to replace with. */
|
||||
private final String value;
|
||||
|
||||
TagValue(String tag, String value) {
|
||||
this.tag = tag;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TagValue[tag='" + tag + "', value='" + value + "']";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package fr.xephi.authme.util.lazytags;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Applies tags lazily to the String property of an item. This class wraps
|
||||
* a {@link TagReplacer} with the extraction of the String property and
|
||||
* the creation of new items with the adapted string property.
|
||||
*
|
||||
* @param <T> the item type
|
||||
* @param <A> the argument type to evaluate the replacements
|
||||
*/
|
||||
public class WrappedTagReplacer<T, A> {
|
||||
|
||||
private final Collection<T> items;
|
||||
private final BiFunction<T, String, ? extends T> itemCreator;
|
||||
private final TagReplacer<A> tagReplacer;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param allTags all available tags
|
||||
* @param items the items to apply the replacements on
|
||||
* @param stringGetter getter of the String property to adapt on the items
|
||||
* @param itemCreator a function of signature (T, String) -> T: the original item and the adapted String are passed
|
||||
*/
|
||||
public WrappedTagReplacer(Collection<Tag<A>> allTags,
|
||||
Collection<T> items,
|
||||
Function<? super T, String> stringGetter,
|
||||
BiFunction<T, String, ? extends T> itemCreator) {
|
||||
this.items = items;
|
||||
this.itemCreator = itemCreator;
|
||||
|
||||
List<String> stringItems = items.stream().map(stringGetter).collect(Collectors.toList());
|
||||
tagReplacer = TagReplacer.newReplacer(allTags, stringItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates adapted items for the given argument.
|
||||
*
|
||||
* @param argument the argument to adapt the items for
|
||||
* @return the adapted items
|
||||
*/
|
||||
public List<T> getAdaptedItems(A argument) {
|
||||
List<String> adaptedStrings = tagReplacer.getAdaptedMessages(argument);
|
||||
List<T> adaptedItems = new LinkedList<>();
|
||||
|
||||
Iterator<T> originalItemsIter = items.iterator();
|
||||
Iterator<String> newStringsIter = adaptedStrings.iterator();
|
||||
while (originalItemsIter.hasNext() && newStringsIter.hasNext()) {
|
||||
adaptedItems.add(itemCreator.apply(originalItemsIter.next(), newStringsIter.next()));
|
||||
}
|
||||
return adaptedItems;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user