001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.plot.flag; 020 021import com.google.common.base.Preconditions; 022import com.plotsquared.core.configuration.caption.Caption; 023import org.checkerframework.checker.nullness.qual.NonNull; 024 025import java.util.Collection; 026import java.util.Collections; 027 028/** 029 * A plot flag is any property that can be assigned 030 * to a plot, that will alter its functionality in some way. 031 * These are user assignable in-game, or via configuration files. 032 * 033 * @param <T> Value contained in the flag. 034 */ 035public abstract class PlotFlag<T, F extends PlotFlag<T, F>> { 036 037 private final T value; 038 private final Caption flagCategory; 039 private final Caption flagDescription; 040 private final String flagName; 041 042 /** 043 * Construct a new flag instance. 044 * 045 * @param value Flag value 046 * @param flagCategory The flag category 047 * @param flagDescription A caption describing the flag functionality 048 */ 049 protected PlotFlag( 050 final @NonNull T value, final @NonNull Caption flagCategory, 051 final @NonNull Caption flagDescription 052 ) { 053 this.value = Preconditions.checkNotNull(value, "flag value may not be null"); 054 this.flagCategory = 055 Preconditions.checkNotNull(flagCategory, "flag category may not be null"); 056 this.flagDescription = 057 Preconditions.checkNotNull(flagDescription, "flag description may not be null"); 058 // Parse flag name 059 // noinspection unchecked 060 this.flagName = getFlagName(this.getClass()); 061 } 062 063 /** 064 * Return the name of the flag. 065 * 066 * @param flagClass Flag class 067 * @param <T> Value type 068 * @param <F> Flag type 069 * @return The name of the flag implemented by the given class 070 */ 071 public static <T, F extends PlotFlag<T, F>> String getFlagName(Class<F> flagClass) { 072 final StringBuilder flagName = new StringBuilder(); 073 final char[] chars = flagClass.getSimpleName().replace("Flag", "").toCharArray(); 074 for (int i = 0; i < chars.length; i++) { 075 if (i == 0) { 076 flagName.append(Character.toLowerCase(chars[i])); 077 } else if (Character.isUpperCase(chars[i])) { 078 flagName.append('-').append(Character.toLowerCase(chars[i])); 079 } else { 080 flagName.append(chars[i]); 081 } 082 } 083 return flagName.toString(); 084 } 085 086 /** 087 * Get the flag value 088 * 089 * @return Non-nullable flag value 090 */ 091 public @NonNull 092 final T getValue() { 093 return this.value; 094 } 095 096 /** 097 * Parse a string into a flag, and throw an exception in the case that the 098 * string does not represent a valid flag value. This instance won't change its 099 * state, but instead an instance holding the parsed flag value will be returned. 100 * 101 * @param input String to parse. 102 * @return Parsed value, if valid. 103 * @throws FlagParseException If the value could not be parsed. 104 */ 105 public abstract F parse(final @NonNull String input) throws FlagParseException; 106 107 /** 108 * Merge this flag's value with another value and return an instance 109 * holding the merged value. 110 * 111 * @param newValue New flag value. 112 * @return Flag containing parsed flag value. 113 */ 114 public abstract F merge(final @NonNull T newValue); 115 116 /** 117 * Returns a string representation of the flag instance, that when 118 * passed through {@link #parse(String)} will result in an equivalent 119 * instance of the flag. 120 * 121 * @return String representation of the flag 122 */ 123 public abstract String toString(); 124 125 /** 126 * Get the flag name. 127 * 128 * @return Flag name 129 */ 130 public final String getName() { 131 return this.flagName; 132 } 133 134 /** 135 * Get a simple caption that describes the flag usage. 136 * 137 * @return Flag description. 138 */ 139 public Caption getFlagDescription() { 140 return this.flagDescription; 141 } 142 143 /** 144 * Get the category this flag belongs to. Usually a caption from {@link com.plotsquared.core.configuration.caption.TranslatableCaption} 145 * <p> 146 * These categories are used to categorize the flags when outputting 147 * flag lists to players. 148 * 149 * @return Flag category 150 */ 151 public Caption getFlagCategory() { 152 return this.flagCategory; 153 } 154 155 /** 156 * Get if the flag's permission should check for values. E.g. plots.flag.set.music.VALUE 157 * 158 * @return if valued permission 159 * @since 6.0.10 160 */ 161 public boolean isValuedPermission() { 162 return true; 163 } 164 165 /** 166 * An example of a string that would parse into a valid 167 * flag value. 168 * 169 * @return An example flag value. 170 */ 171 public abstract String getExample(); 172 173 protected abstract F flagOf(@NonNull T value); 174 175 /** 176 * Create a new instance of the flag using a provided 177 * (non-null) value. 178 * 179 * @param value The flag value 180 * @return The created flag instance 181 */ 182 public final F createFlagInstance(final @NonNull T value) { 183 return flagOf(Preconditions.checkNotNull(value)); 184 } 185 186 /** 187 * Get the tab completable values associated with the flag type, or 188 * an empty collection if tab completion isn't supported. 189 * 190 * @return Collection containing tab completable flag values 191 */ 192 public Collection<String> getTabCompletions() { 193 return Collections.emptyList(); 194 } 195 196 @Override 197 public boolean equals(final Object o) { 198 if (this == o) { 199 return true; 200 } 201 if (o == null || getClass() != o.getClass()) { 202 return false; 203 } 204 final PlotFlag<?, ?> plotFlag = (PlotFlag<?, ?>) o; 205 return value.equals(plotFlag.value); 206 } 207 208 @Override 209 public int hashCode() { 210 return value.hashCode(); 211 } 212 213 /** 214 * @deprecated This method is not meant to be invoked or overridden, with no replacement. 215 */ 216 @Deprecated(forRemoval = true, since = "6.6.0") 217 protected boolean canEqual(final Object other) { 218 return other instanceof PlotFlag; 219 } 220 221 222}