Make PlotFlag more generic to allow generic flag creation

This commit is contained in:
Hannes Greule 2020-02-11 23:33:05 +01:00
parent b3db67ab76
commit 1c4c680e18
9 changed files with 77 additions and 70 deletions

View File

@ -11,7 +11,7 @@ import java.util.Map;
@EqualsAndHashCode(of = "flagMap") public class FlagContainer { @EqualsAndHashCode(of = "flagMap") public class FlagContainer {
private final FlagContainer parentContainer; private final FlagContainer parentContainer;
private final Map<Class<?>, PlotFlag<?>> flagMap = new HashMap<>(); private final Map<Class<?>, PlotFlag<?, ?>> flagMap = new HashMap<>();
public FlagContainer(@Nullable final FlagContainer parentContainer) { public FlagContainer(@Nullable final FlagContainer parentContainer) {
this.parentContainer = parentContainer; this.parentContainer = parentContainer;
@ -21,25 +21,25 @@ import java.util.Map;
return this.parentContainer; return this.parentContainer;
} }
protected Map<Class<?>, PlotFlag<?>> getInternalPlotFlagMap() { protected Map<Class<?>, PlotFlag<?, ?>> getInternalPlotFlagMap() {
return this.flagMap; return this.flagMap;
} }
public Map<Class<?>, PlotFlag<?>> getFlagMap() { public Map<Class<?>, PlotFlag<?, ?>> getFlagMap() {
return ImmutableMap.<Class<?>, PlotFlag<?>>builder().putAll(this.flagMap).build(); return ImmutableMap.<Class<?>, PlotFlag<?, ?>>builder().putAll(this.flagMap).build();
} }
public void addFlag(final PlotFlag<?> flag) { public void addFlag(final PlotFlag<?, ? extends PlotFlag<?, ?>> flag) {
this.flagMap.put(flag.getClass(), flag); this.flagMap.put(flag.getClass(), flag);
} }
public void addAll(final Collection<PlotFlag<?>> flags) { public void addAll(final Collection<PlotFlag<?, ?>> flags) {
for (final PlotFlag<?> flag : flags) { for (final PlotFlag<?, ?> flag : flags) {
this.addFlag(flag); this.addFlag(flag);
} }
} }
public Collection<PlotFlag<?>> getRecognizedPlotFlags() { public Collection<PlotFlag<?, ?>> getRecognizedPlotFlags() {
return this.getHighestClassContainer().getFlagMap().values(); return this.getHighestClassContainer().getFlagMap().values();
} }
@ -50,8 +50,8 @@ import java.util.Map;
return this; return this;
} }
public PlotFlag<?> getFlagErased(Class<?> flagClass) { public PlotFlag<?, ?> getFlagErased(Class<?> flagClass) {
final PlotFlag<?> flag = this.flagMap.get(flagClass); final PlotFlag<?, ?> flag = this.flagMap.get(flagClass);
if (flag != null) { if (flag != null) {
return flag; return flag;
} else { } else {
@ -62,10 +62,10 @@ import java.util.Map;
return null; return null;
} }
public <T> PlotFlag<T> getFlag(final Class<? extends PlotFlag<T>> flagClass) { public <T> PlotFlag<T, ?> getFlag(final Class<? extends PlotFlag<T, ?>> flagClass) {
final PlotFlag<?> flag = this.flagMap.get(flagClass); final PlotFlag<?, ?> flag = this.flagMap.get(flagClass);
if (flag != null) { if (flag != null) {
return (PlotFlag<T>) flag; return (PlotFlag<T, ?>) flag;
} else { } else {
if (getParentContainer() != null) { if (getParentContainer() != null) {
return getParentContainer().getFlag(flagClass); return getParentContainer().getFlag(flagClass);

View File

@ -14,8 +14,8 @@ public final class GlobalFlagContainer extends FlagContainer {
private final Map<String, Class<?>> stringClassMap = new HashMap<>(); private final Map<String, Class<?>> stringClassMap = new HashMap<>();
@Override public PlotFlag<?> getFlagErased(Class<?> flagClass) { @Override public PlotFlag<?, ?> getFlagErased(Class<?> flagClass) {
final PlotFlag<?> flag = super.getFlagErased(flagClass); final PlotFlag<?, ?> flag = super.getFlagErased(flagClass);
if (flag != null) { if (flag != null) {
return flag; return flag;
} else { } else {
@ -24,10 +24,10 @@ public final class GlobalFlagContainer extends FlagContainer {
} }
} }
@Nonnull @Override public <T> PlotFlag<T> getFlag(Class<? extends PlotFlag<T>> flagClass) { @Nonnull @Override public <T> PlotFlag<T, ?> getFlag(Class<? extends PlotFlag<T, ?>> flagClass) {
final PlotFlag<?> flag = super.getFlag(flagClass); final PlotFlag<?, ?> flag = super.getFlag(flagClass);
if (flag != null) { if (flag != null) {
return (PlotFlag<T>) flag; return (PlotFlag<T, ?>) flag;
} else { } else {
throw new IllegalStateException(String.format("Unrecognized flag '%s'. All flag types" throw new IllegalStateException(String.format("Unrecognized flag '%s'. All flag types"
+ " must be present in the global flag container.", flagClass.getSimpleName())); + " must be present in the global flag container.", flagClass.getSimpleName()));
@ -37,10 +37,10 @@ public final class GlobalFlagContainer extends FlagContainer {
private GlobalFlagContainer() { private GlobalFlagContainer() {
super(null); super(null);
// Register all default flags here // Register all default flags here
this.addFlag(new ExplosionFlag()); this.addFlag(ExplosionFlag.EXPLOSION_FALSE);
} }
@Override public void addFlag(PlotFlag<?> flag) { @Override public void addFlag(PlotFlag<?, ?> flag) {
super.addFlag(flag); super.addFlag(flag);
this.stringClassMap.put(flag.getName().toLowerCase(Locale.ENGLISH), flag.getClass()); this.stringClassMap.put(flag.getName().toLowerCase(Locale.ENGLISH), flag.getClass());
} }
@ -49,7 +49,7 @@ public final class GlobalFlagContainer extends FlagContainer {
return this.stringClassMap.get(name.toLowerCase(Locale.ENGLISH)); return this.stringClassMap.get(name.toLowerCase(Locale.ENGLISH));
} }
public PlotFlag<?> getFlagFromString(final String name) { public PlotFlag<?, ?> getFlagFromString(final String name) {
final Class<?> flagClass = this.getFlagClassFromString(name); final Class<?> flagClass = this.getFlagClassFromString(name);
if (flagClass == null) { if (flagClass == null) {
return null; return null;

View File

@ -14,9 +14,9 @@ import java.util.Locale;
* *
* @param <T> Value contained in the flag. * @param <T> Value contained in the flag.
*/ */
@EqualsAndHashCode(of = "value") public abstract class PlotFlag<T> { @EqualsAndHashCode(of = "value") public abstract class PlotFlag<T, F extends PlotFlag<T, F>> {
private T value; private final T value;
private final Captions flagCategory; private final Captions flagCategory;
private final Captions flagDescription; private final Captions flagDescription;
@ -42,33 +42,24 @@ import java.util.Locale;
} }
/** /**
* Update the flag value. * Parse a string into a flag, and throw an exception in the case that the
* * string does not represent a valid flag value. This instance won't change its
* @param newValue New flag value. * state, but instead an instance holding the parsed flag value will be returned.
*/
public T setFlagValue(@NotNull final T newValue) {
return (this.value = Preconditions.checkNotNull(newValue, "flag values may not be null"));
}
/**
* Parse a string into a flag value, and throw an exception in the case that the
* string does not represent a valid flag value. The flag value will be updated to
* the newly parsed value.
* *
* @param input String to parse. * @param input String to parse.
* @return Parsed value, if valid. * @return Parsed value, if valid.
* @throws FlagParseException If the value could not be parsed. * @throws FlagParseException If the value could not be parsed.
*/ */
public abstract T parse(@NotNull final String input) throws FlagParseException; public abstract F parse(@NotNull final String input) throws FlagParseException;
/** /**
* Merge two flag values into one and updates the flag value. * Merge this flag's value with another value and return an instance
* holding the merged value.
* *
* @param oldValue Existing flag value.
* @param newValue New flag value. * @param newValue New flag value.
* @return Flag containing parsed flag value. * @return Flag containing parsed flag value.
*/ */
public abstract T merge(@NotNull final T oldValue, @NotNull final T newValue); public abstract F merge(@NotNull final T newValue);
/** /**
* Returns a string representation of the flag instance, that when * Returns a string representation of the flag instance, that when
@ -93,4 +84,6 @@ import java.util.Locale;
public abstract String getExample(); public abstract String getExample();
protected abstract F flagOf(@NotNull T value);
} }

View File

@ -2,15 +2,21 @@ package com.github.intellectualsites.plotsquared.plot.flags.implementations;
import com.github.intellectualsites.plotsquared.plot.config.Captions; import com.github.intellectualsites.plotsquared.plot.config.Captions;
import com.github.intellectualsites.plotsquared.plot.flags.types.BooleanFlag; import com.github.intellectualsites.plotsquared.plot.flags.types.BooleanFlag;
import org.jetbrains.annotations.NotNull;
public class ExplosionFlag extends BooleanFlag { public class ExplosionFlag extends BooleanFlag<ExplosionFlag> {
public static final ExplosionFlag EXPLOSION_TRUE = new ExplosionFlag(true);
public static final ExplosionFlag EXPLOSION_FALSE = new ExplosionFlag(false);
public ExplosionFlag() { private ExplosionFlag(boolean value) {
super(Captions.FLAG_DESCRIPTION_EXPLOSION); super(value, Captions.FLAG_DESCRIPTION_EXPLOSION);
} }
@Override public String getExample() { @Override public String getExample() {
return "true"; return "true";
} }
@Override protected ExplosionFlag flagOf(@NotNull Boolean value) {
return value ? EXPLOSION_TRUE : EXPLOSION_FALSE;
}
} }

View File

@ -10,17 +10,17 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class BlockTypeListFlag extends ListFlag<BlockType> { public class BlockTypeListFlag extends ListFlag<BlockType, BlockTypeListFlag> {
public BlockTypeListFlag(Captions description) { public BlockTypeListFlag(List<BlockType> blockTypeList, Captions description) {
super(Captions.FLAG_CATEGORY_BLOCK_LIST, description); super(blockTypeList, Captions.FLAG_CATEGORY_BLOCK_LIST, description);
} }
@Override public List<BlockType> parse(@NotNull String input) throws FlagParseException { @Override public BlockTypeListFlag parse(@NotNull String input) throws FlagParseException {
final List<BlockType> parsedBlocks = new ArrayList<>(); final List<BlockType> parsedBlocks = new ArrayList<>();
final String[] split = input.split(",(?![^\\(\\[]*[\\]\\)])"); final String[] split = input.split(",(?![^\\(\\[]*[\\]\\)])");
if (split.length == 0) { if (split.length == 0) {
return parsedBlocks; return this.flagOf(parsedBlocks);
} }
for (final String blockString : split) { for (final String blockString : split) {
final BlockState blockState = BlockUtil.get(blockString); final BlockState blockState = BlockUtil.get(blockString);
@ -30,11 +30,15 @@ public class BlockTypeListFlag extends ListFlag<BlockType> {
parsedBlocks.add(blockState.getBlockType()); parsedBlocks.add(blockState.getBlockType());
} }
} }
return parsedBlocks; return this.flagOf(parsedBlocks);
} }
@Override public String getExample() { @Override public String getExample() {
return "air,grass_block"; return "air,grass_block";
} }
@Override protected BlockTypeListFlag flagOf(@NotNull List<BlockType> value) {
return new BlockTypeListFlag(value, getFlagDescription()); // copy the description
}
} }

View File

@ -9,7 +9,7 @@ import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Locale; import java.util.Locale;
public abstract class BooleanFlag extends PlotFlag<Boolean> { public abstract class BooleanFlag<F extends PlotFlag<Boolean, F>> extends PlotFlag<Boolean, F> {
private static final Collection<String> positiveValues = Arrays.asList("1", "yes", "allow", "true"); private static final Collection<String> positiveValues = Arrays.asList("1", "yes", "allow", "true");
private static final Collection<String> negativeValues = Arrays.asList("0", "no", "deny", "disallow", "false"); private static final Collection<String> negativeValues = Arrays.asList("0", "no", "deny", "disallow", "false");
@ -34,18 +34,18 @@ public abstract class BooleanFlag extends PlotFlag<Boolean> {
this(false, description); this(false, description);
} }
@Override public Boolean parse(@NotNull String input) throws FlagParseException { @Override public F parse(@NotNull String input) throws FlagParseException {
if (positiveValues.contains(input.toLowerCase(Locale.ENGLISH))) { if (positiveValues.contains(input.toLowerCase(Locale.ENGLISH))) {
return true; return this.flagOf(true);
} else if (negativeValues.contains(input.toLowerCase(Locale.ENGLISH))) { } else if (negativeValues.contains(input.toLowerCase(Locale.ENGLISH))) {
return false; return this.flagOf(false);
} else { } else {
throw new FlagParseException(this, input, Captions.FLAG_ERROR_BOOLEAN); throw new FlagParseException(this, input, Captions.FLAG_ERROR_BOOLEAN);
} }
} }
@Override public Boolean merge(@NotNull Boolean oldValue, @NotNull Boolean newValue) { @Override public F merge(@NotNull Boolean newValue) {
return this.setFlagValue(oldValue || newValue); return this.flagOf(getValue() || newValue);
} }
@Override public String toString() { @Override public String toString() {

View File

@ -5,26 +5,26 @@ import com.github.intellectualsites.plotsquared.plot.flags.FlagParseException;
import com.github.intellectualsites.plotsquared.plot.flags.PlotFlag; import com.github.intellectualsites.plotsquared.plot.flags.PlotFlag;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class IntegerFlag extends PlotFlag<Integer> { public class IntegerFlag extends PlotFlag<Integer, IntegerFlag> {
protected IntegerFlag(final int defaultValue, @NotNull Captions flagDescription) { protected IntegerFlag(final int value, @NotNull Captions flagDescription) {
super(defaultValue, Captions.FLAG_CATEGORY_INTEGERS, flagDescription); super(value, Captions.FLAG_CATEGORY_INTEGERS, flagDescription);
} }
protected IntegerFlag(@NotNull Captions flagDescription) { protected IntegerFlag(@NotNull Captions flagDescription) {
this(0, flagDescription); this(0, flagDescription);
} }
@Override public Integer parse(@NotNull String input) throws FlagParseException { @Override public IntegerFlag parse(@NotNull String input) throws FlagParseException {
try { try {
return Integer.parseInt(input); return flagOf(Integer.parseInt(input));
} catch (final Throwable throwable) { } catch (final Throwable throwable) {
throw new FlagParseException(this, input, Captions.FLAG_ERROR_INTEGER); throw new FlagParseException(this, input, Captions.FLAG_ERROR_INTEGER);
} }
} }
@Override public Integer merge(@NotNull Integer oldValue, @NotNull Integer newValue) { @Override public IntegerFlag merge(@NotNull Integer newValue) {
return oldValue + newValue; return flagOf(getValue() + newValue);
} }
@Override public String toString() { @Override public String toString() {
@ -35,4 +35,8 @@ public class IntegerFlag extends PlotFlag<Integer> {
return "10"; return "10";
} }
@Override protected IntegerFlag flagOf(@NotNull Integer value) {
return new IntegerFlag(value, getFlagDescription());
}
} }

View File

@ -8,17 +8,17 @@ import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public abstract class ListFlag<V> extends PlotFlag<List<V>> { public abstract class ListFlag<V, F extends PlotFlag<List<V>, F>> extends PlotFlag<List<V>, F> {
public ListFlag(final Captions category, final Captions description) { public ListFlag(final List<V> valueList, final Captions category, final Captions description) {
super(new ArrayList<>(), category, description); super(valueList, category, description);
} }
@Override public List<V> merge(@NotNull List<V> oldValue, @NotNull List<V> newValue) { @Override public F merge(@NotNull List<V> newValue) {
final List<V> mergedList = new ArrayList<>(); final List<V> mergedList = new ArrayList<>();
mergedList.addAll(oldValue); mergedList.addAll(getValue());
mergedList.addAll(newValue); mergedList.addAll(newValue);
return this.setFlagValue(mergedList); return this.flagOf(mergedList);
} }
@Override public String toString() { @Override public String toString() {

View File

@ -213,7 +213,7 @@ public class Plot {
* @see Plot#getPlot(Location) for existing plots * @see Plot#getPlot(Location) for existing plots
*/ */
public Plot(@NotNull PlotId id, UUID owner, HashSet<UUID> trusted, HashSet<UUID> members, public Plot(@NotNull PlotId id, UUID owner, HashSet<UUID> trusted, HashSet<UUID> members,
HashSet<UUID> denied, String alias, BlockLoc position, Collection<PlotFlag<?>> flags, HashSet<UUID> denied, String alias, BlockLoc position, Collection<PlotFlag<?, ?>> flags,
PlotArea area, boolean[] merged, long timestamp, int temp) { PlotArea area, boolean[] merged, long timestamp, int temp) {
this.id = id; this.id = id;
this.area = area; this.area = area;
@ -229,7 +229,7 @@ public class Plot {
this.temp = temp; this.temp = temp;
this.flagContainer = new FlagContainer(area.getFlagContainer()); this.flagContainer = new FlagContainer(area.getFlagContainer());
if (flags != null) { if (flags != null) {
for (PlotFlag<?> flag : flags) { for (PlotFlag<?, ?> flag : flags) {
this.flagContainer.addFlag(flag); this.flagContainer.addFlag(flag);
} }
} }
@ -3148,7 +3148,7 @@ public class Plot {
return getMerged(direction.getIndex()); return getMerged(direction.getIndex());
} }
public <T> T getFlag(final Class<? extends PlotFlag<T>> flagClass) { public <T> T getFlag(final Class<? extends PlotFlag<T, ?>> flagClass) {
return this.flagContainer.getFlag(flagClass).getValue(); return this.flagContainer.getFlag(flagClass).getValue();
} }