diff options
Diffstat (limited to 'bukkit/src')
12 files changed, 220 insertions, 140 deletions
diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminItemsCommandHandler.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminItemsCommandHandler.java index 6eb6b36f..32558673 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminItemsCommandHandler.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/command/AdminItemsCommandHandler.java @@ -3,7 +3,7 @@ package com.leonardobishop.quests.bukkit.command; import com.leonardobishop.quests.bukkit.BukkitQuestsPlugin; import com.leonardobishop.quests.bukkit.item.ParsedQuestItem; import com.leonardobishop.quests.bukkit.item.QuestItem; -import com.leonardobishop.quests.bukkit.util.StringUtils; +import com.leonardobishop.quests.bukkit.util.lang3.StringUtils; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.command.CommandSender; diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/config/BukkitQuestsLoader.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/config/BukkitQuestsLoader.java index 5a16d283..8f867673 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/config/BukkitQuestsLoader.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/config/BukkitQuestsLoader.java @@ -11,7 +11,7 @@ import com.leonardobishop.quests.bukkit.item.QuestItemRegistry; import com.leonardobishop.quests.bukkit.item.SlimefunQuestItem; import com.leonardobishop.quests.bukkit.menu.itemstack.QItemStack; import com.leonardobishop.quests.bukkit.menu.itemstack.QItemStackRegistry; -import com.leonardobishop.quests.bukkit.util.StringUtils; +import com.leonardobishop.quests.bukkit.util.lang3.StringUtils; import com.leonardobishop.quests.bukkit.util.chat.Chat; import com.leonardobishop.quests.common.config.ConfigProblem; import com.leonardobishop.quests.common.config.ConfigProblemDescriptions; diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/menu/PaginatedQMenu.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/menu/PaginatedQMenu.java index 1947c738..39adf59a 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/menu/PaginatedQMenu.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/menu/PaginatedQMenu.java @@ -11,7 +11,7 @@ import com.leonardobishop.quests.bukkit.menu.element.PageNextMenuElement; import com.leonardobishop.quests.bukkit.menu.element.PagePrevMenuElement; import com.leonardobishop.quests.bukkit.menu.element.SpacerMenuElement; import com.leonardobishop.quests.bukkit.util.MenuUtils; -import com.leonardobishop.quests.bukkit.util.StringUtils; +import com.leonardobishop.quests.bukkit.util.lang3.StringUtils; import com.leonardobishop.quests.common.player.QPlayer; import org.bukkit.Bukkit; import org.bukkit.entity.Player; diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/CommandTaskType.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/CommandTaskType.java index 62162833..0c49559a 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/CommandTaskType.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/CommandTaskType.java @@ -23,6 +23,7 @@ public final class CommandTaskType extends BukkitTaskType { super.addConfigValidator(TaskUtils.useRequiredConfigValidator(this, "command")); super.addConfigValidator(TaskUtils.useBooleanConfigValidator(this, "ignore-case")); + super.addConfigValidator(TaskUtils.useEnumConfigValidator(this, TaskUtils.StringMatchMode.class, "command-match-mode")); } @EventHandler(priority = EventPriority.MONITOR) @@ -51,7 +52,7 @@ public final class CommandTaskType extends BukkitTaskType { boolean ignoreCase = TaskUtils.getConfigBoolean(task, "ignore-case"); - if (!TaskUtils.matchString(this, pendingTask, message, player.getUniqueId(), "command", "commands", false, ignoreCase)) { + if (!TaskUtils.matchString(this, pendingTask, message,player.getUniqueId(), "command", "commands", false, "command-match-mode", ignoreCase)) { super.debug("Continuing...", quest.getId(), task.getId(), player.getUniqueId()); continue; } diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/MobkillingTaskType.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/MobkillingTaskType.java index e0d85ba1..28f78554 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/MobkillingTaskType.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/MobkillingTaskType.java @@ -39,6 +39,7 @@ public final class MobkillingTaskType extends BukkitTaskType { super.addConfigValidator(TaskUtils.useItemStackConfigValidator(this, "item")); super.addConfigValidator(TaskUtils.useIntegerConfigValidator(this, "data")); super.addConfigValidator(TaskUtils.useBooleanConfigValidator(this, "exact-match")); + super.addConfigValidator(TaskUtils.useEnumConfigValidator(this, TaskUtils.StringMatchMode.class, "name-match-mode")); if (plugin.getQuestsConfig().getBoolean("options.mobkilling-use-wildstacker-hook", true)) { try { @@ -132,7 +133,7 @@ public final class MobkillingTaskType extends BukkitTaskType { continue; } - if (!TaskUtils.matchString(this, pendingTask, customName, player.getUniqueId(), "name", "names", true, false)) { + if (!TaskUtils.matchString(this, pendingTask, customName, player.getUniqueId(), "name", "names", true, "name-match-mode", false)) { super.debug("Continuing...", quest.getId(), task.getId(), player.getUniqueId()); continue; } diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/EcoBossesKillingTaskType.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/EcoBossesKillingTaskType.java index a420c853..1f833e5a 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/EcoBossesKillingTaskType.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/EcoBossesKillingTaskType.java @@ -26,6 +26,7 @@ public final class EcoBossesKillingTaskType extends BukkitTaskType { super.addConfigValidator(TaskUtils.useRequiredConfigValidator(this, "id", "ids")); super.addConfigValidator(TaskUtils.useRequiredConfigValidator(this, "amount")); super.addConfigValidator(TaskUtils.useIntegerConfigValidator(this, "amount")); + super.addConfigValidator(TaskUtils.useEnumConfigValidator(this, TaskUtils.StringMatchMode.class, "id-match-mode")); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @@ -50,7 +51,7 @@ public final class EcoBossesKillingTaskType extends BukkitTaskType { super.debug("Player killed EcoBosses boss '" + ecoBoss.getDisplayName() + "' (id = " + ecoBoss.getID() + ")", quest.getId(), task.getId(), player.getUniqueId()); - if (!TaskUtils.matchString(this, pendingTask, ecoBoss.getID(), player.getUniqueId(), "id", "ids", false, false)) { + if (!TaskUtils.matchString(this, pendingTask, ecoBoss.getID(), player.getUniqueId(), "id", "ids", false, "id-match-mode", false)) { super.debug("Continuing...", quest.getId(), task.getId(), player.getUniqueId()); continue; } diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/EcoMobsKillingTaskType.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/EcoMobsKillingTaskType.java index c10aca6b..e9aa5030 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/EcoMobsKillingTaskType.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/EcoMobsKillingTaskType.java @@ -26,6 +26,7 @@ public final class EcoMobsKillingTaskType extends BukkitTaskType { super.addConfigValidator(TaskUtils.useRequiredConfigValidator(this, "id", "ids")); super.addConfigValidator(TaskUtils.useRequiredConfigValidator(this, "amount")); super.addConfigValidator(TaskUtils.useIntegerConfigValidator(this, "amount")); + super.addConfigValidator(TaskUtils.useEnumConfigValidator(this, TaskUtils.StringMatchMode.class, "id-match-mode")); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @@ -50,7 +51,7 @@ public final class EcoMobsKillingTaskType extends BukkitTaskType { super.debug("Player killed EcoMobs mob '" + mob.getDisplayName() + "' (id = " + mob.getMob().getID() + ")", quest.getId(), task.getId(), player.getUniqueId()); - if (!TaskUtils.matchString(this, pendingTask, ecoMob.getID(), player.getUniqueId(), "id", "ids", false, false)) { + if (!TaskUtils.matchString(this, pendingTask, ecoMob.getID(), player.getUniqueId(), "id", "ids", false, "id-match-mode", false)) { super.debug("Continuing...", quest.getId(), task.getId(), player.getUniqueId()); continue; } diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/MythicMobsKillingTaskType.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/MythicMobsKillingTaskType.java index eaf64292..f481a5ac 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/MythicMobsKillingTaskType.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/dependent/MythicMobsKillingTaskType.java @@ -31,6 +31,7 @@ public final class MythicMobsKillingTaskType extends BukkitTaskType { super.addConfigValidator(TaskUtils.useIntegerConfigValidator(this, "amount")); super.addConfigValidator(TaskUtils.useIntegerConfigValidator(this, "level")); super.addConfigValidator(TaskUtils.useIntegerConfigValidator(this, "min-level")); + super.addConfigValidator(TaskUtils.useEnumConfigValidator(this, TaskUtils.StringMatchMode.class, "name-match-mode")); // MythicMobs 4 try { @@ -103,7 +104,7 @@ public final class MythicMobsKillingTaskType extends BukkitTaskType { super.debug("Player killed mythic mob '" + mobName + "' (level = " + level + ")", quest.getId(), task.getId(), player.getUniqueId()); - if (!TaskUtils.matchString(this, pendingTask, mobName, player.getUniqueId(), "name", "names", false, false)) { + if (!TaskUtils.matchString(this, pendingTask, mobName, player.getUniqueId(), "name", "names", false, "name-match-mode", false)) { super.debug("Continuing...", quest.getId(), task.getId(), player.getUniqueId()); continue; } diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/StringUtils.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/StringUtils.java deleted file mode 100644 index ea44fef6..00000000 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/StringUtils.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.leonardobishop.quests.bukkit.util; - -import java.lang.reflect.Array; - -/* - * From Apache Commons Lang - * https://github.com/apache/commons-lang/blob/master/LICENSE.txt - */ -public class StringUtils { - public static boolean isEmpty(final CharSequence cs) { - return cs == null || cs.length() == 0; - } - - public static boolean isAlphanumeric(final CharSequence cs) { - if (isEmpty(cs)) { - return false; - } - - final int sz = cs.length(); - for (int i = 0; i < sz; i++) { - final char c = cs.charAt(i); - if (!(Character.isLetterOrDigit(c) || c == '_' || c == '-')) { - return false; - } - } - - return true; - } - - public static boolean isNumeric(final CharSequence cs) { - if (isEmpty(cs)) { - return false; - } - final int sz = cs.length(); - for (int i = 0; i < sz; i++) { - if (!Character.isDigit(cs.charAt(i))) { - return false; - } - } - return true; - } - - public static boolean equals(final CharSequence cs1, final CharSequence cs2, final boolean ignoreCase) { - if (cs1 == cs2) { - return true; - } - if (cs1 == null || cs2 == null) { - return false; - } - if (cs1.length() != cs2.length()) { - return false; - } - return regionMatches(cs1, ignoreCase, 0, cs2, 0, cs1.length()); - } - - static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart, - final CharSequence substring, final int start, final int length) { - if (cs instanceof String && substring instanceof String) { - return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length); - } - int index1 = thisStart; - int index2 = start; - int tmpLen = length; - - // Extract these first so we detect NPEs the same as the java.lang.String version - final int srcLen = cs.length() - thisStart; - final int otherLen = substring.length() - start; - - // Check for invalid parameters - if (thisStart < 0 || start < 0 || length < 0) { - return false; - } - - // Check that the regions are long enough - if (srcLen < length || otherLen < length) { - return false; - } - - while (tmpLen-- > 0) { - final char c1 = cs.charAt(index1++); - final char c2 = substring.charAt(index2++); - - if (c1 == c2) { - continue; - } - - if (!ignoreCase) { - return false; - } - - // The real same check as in String.regionMatches(): - final char u1 = Character.toUpperCase(c1); - final char u2 = Character.toUpperCase(c2); - if (u1 != u2 && Character.toLowerCase(u1) != Character.toLowerCase(u2)) { - return false; - } - } - - return true; - } - - public static boolean equalsAny(final CharSequence string, final CharSequence[] searchStrings, final boolean ignoreCase) { - if (isNotEmpty(searchStrings)) { - for (final CharSequence next : searchStrings) { - if (equals(string, next, ignoreCase)) { - return true; - } - } - } - return false; - } - - public static <T> boolean isNotEmpty(final T[] array) { - return !isEmpty(array); - } - - public static boolean isEmpty(final Object[] array) { - return isArrayEmpty(array); - } - - private static boolean isArrayEmpty(final Object array) { - return getLength(array) == 0; - } - - public static int getLength(final Object array) { - return array != null ? Array.getLength(array) : 0; - } -} diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/TaskUtils.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/TaskUtils.java index ec966576..dfcbdcef 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/TaskUtils.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/TaskUtils.java @@ -8,6 +8,7 @@ import com.leonardobishop.quests.bukkit.tasktype.BukkitTaskType; import com.leonardobishop.quests.bukkit.util.chat.Chat; import com.leonardobishop.quests.bukkit.util.constraint.TaskConstraint; import com.leonardobishop.quests.bukkit.util.constraint.TaskConstraintSet; +import com.leonardobishop.quests.bukkit.util.lang3.StringUtils; import com.leonardobishop.quests.common.config.ConfigProblem; import com.leonardobishop.quests.common.config.ConfigProblemDescriptions; import com.leonardobishop.quests.common.player.QPlayer; @@ -483,7 +484,30 @@ public class TaskUtils { return false; } - public static boolean matchString(@NotNull BukkitTaskType type, @NotNull PendingTask pendingTask, @Nullable String string, @NotNull UUID player, final @NotNull String stringKey, final @NotNull String listKey, boolean legacyColor, boolean ignoreCase) { + public enum StringMatchMode { + EQUALS { + @Override + public boolean matches(@NotNull String str1, @NotNull String str2, boolean ignoreCase) { + return StringUtils.equals(str1, str2, ignoreCase); + } + }, + STARTS_WITH { + @Override + public boolean matches(@NotNull String str, @NotNull String prefix, boolean ignoreCase) { + return StringUtils.startsWith(str, prefix, ignoreCase); + } + }, + ENDS_WITH { + @Override + public boolean matches(@NotNull String str, @NotNull String suffix, boolean ignoreCase) { + return StringUtils.endsWith(str, suffix, ignoreCase); + } + }; + + public abstract boolean matches(@NotNull String str1, @NotNull String str2, boolean ignoreCase); + } + + public static boolean matchString(@NotNull BukkitTaskType type, @NotNull PendingTask pendingTask, @Nullable String string, @NotNull UUID player, @NotNull String stringKey, @NotNull String listKey, boolean legacyColor, @NotNull String matchModeKey, boolean ignoreCase) { Task task = pendingTask.task; List<String> checkNames = TaskUtils.getConfigStringList(task, task.getConfigValues().containsKey(stringKey) ? stringKey : listKey); @@ -501,10 +525,21 @@ public class TaskUtils { string = Chat.legacyColor(string); } + StringMatchMode matchMode; + + String matchModeString = (String) task.getConfigValue(matchModeKey); + if (matchModeString != null) { + matchMode = StringMatchMode.valueOf(matchModeString); + } else { + matchMode = StringMatchMode.EQUALS; + } + + type.debug("Utilising " + matchMode + " mode for checking", pendingTask.quest.getId(), task.getId(), player); + for (String name : checkNames) { - type.debug("Checking against name " + name, pendingTask.quest.getId(), task.getId(), player); + type.debug("Checking against name " + string, pendingTask.quest.getId(), task.getId(), player); - if (StringUtils.equals(name, string, ignoreCase)) { + if (matchMode.matches(string, name, ignoreCase)) { type.debug("Name match", pendingTask.quest.getId(), task.getId(), player); return true; } else { @@ -535,10 +570,21 @@ public class TaskUtils { } } + StringMatchMode matchMode; + + String matchModeString = (String) task.getConfigValue(matchModeKey); + if (matchModeString != null) { + matchMode = StringMatchMode.valueOf(matchModeString); + } else { + matchMode = StringMatchMode.EQUALS; + } + + type.debug("Utilising " + matchMode + " mode for checking", pendingTask.quest.getId(), task.getId(), player); + for (String name : checkNames) { type.debug("Checking against name " + name, pendingTask.quest.getId(), task.getId(), player); - if (StringUtils.equalsAny(name, strings, ignoreCase)) { + if (matchMode.matchesAny(strings, name, ignoreCase)) { type.debug("Name match", pendingTask.quest.getId(), task.getId(), player); return true; } else { @@ -1004,6 +1050,27 @@ public class TaskUtils { /** * Returns a config validator which checks if at least one value in the given + * paths is present in the enum. + * + * Should be used for small enums only as it lists possible values in config + * problem extended description. + * + * @param clazz the enum class + * @param paths a list of valid paths for task + * @return config validator + */ + public static <T extends Enum<T>> TaskType.ConfigValidator useEnumConfigValidator(TaskType type, Class<T> clazz, String... paths) { + List<String> acceptedValues = new ArrayList<>(); + T[] constants = clazz.getEnumConstants(); + for (T constant : constants) { + String acceptedValue = constant.name(); + acceptedValues.add(acceptedValue); + } + return useAcceptedValuesConfigValidator(type, acceptedValues, paths); + } + + /** + * Returns a config validator which checks if at least one value in the given * paths is a value in the list of accepted values. * * @param acceptedValues a list of accepted values diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/lang3/CharSequenceUtils.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/lang3/CharSequenceUtils.java new file mode 100644 index 00000000..5728e2de --- /dev/null +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/lang3/CharSequenceUtils.java @@ -0,0 +1,55 @@ +package com.leonardobishop.quests.bukkit.util.lang3; + +/* + * From Apache Commons Lang + * https://github.com/apache/commons-lang/blob/master/LICENSE.txt + */ +public final class CharSequenceUtils { + + // https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/CharSequenceUtils.java#L294-L338 + public static boolean regionMatches(final CharSequence cs, final boolean ignoreCase, final int thisStart, // package -> public + final CharSequence substring, final int start, final int length) { + if (cs instanceof String && substring instanceof String) { + return ((String) cs).regionMatches(ignoreCase, thisStart, (String) substring, start, length); + } + int index1 = thisStart; + int index2 = start; + int tmpLen = length; + + // Extract these first so we detect NPEs the same as the java.lang.String version + final int srcLen = cs.length() - thisStart; + final int otherLen = substring.length() - start; + + // Check for invalid parameters + if (thisStart < 0 || start < 0 || length < 0) { + return false; + } + + // Check that the regions are long enough + if (srcLen < length || otherLen < length) { + return false; + } + + while (tmpLen-- > 0) { + final char c1 = cs.charAt(index1++); + final char c2 = substring.charAt(index2++); + + if (c1 == c2) { + continue; + } + + if (!ignoreCase) { + return false; + } + + // The real same check as in String.regionMatches(): + final char u1 = Character.toUpperCase(c1); + final char u2 = Character.toUpperCase(c2); + if (u1 != u2 && Character.toLowerCase(u1) != Character.toLowerCase(u2)) { + return false; + } + } + + return true; + } +} diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/lang3/StringUtils.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/lang3/StringUtils.java new file mode 100644 index 00000000..5bf93e56 --- /dev/null +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/util/lang3/StringUtils.java @@ -0,0 +1,81 @@ +package com.leonardobishop.quests.bukkit.util.lang3; + +/* + * From Apache Commons Lang + * https://github.com/apache/commons-lang/blob/master/LICENSE.txt + */ +@SuppressWarnings({"BooleanMethodIsAlwaysInverted", "SizeReplaceableByIsEmpty"}) +public final class StringUtils { + + // https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java#L3602-L3604 + public static boolean isEmpty(final CharSequence cs) { + return cs == null || cs.length() == 0; + } + + // https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java#L3361-L3372 + public static boolean isAlphanumeric(final CharSequence cs) { + if (isEmpty(cs)) { + return false; + } + final int sz = cs.length(); + for (int i = 0; i < sz; i++) { + if (!Character.isLetterOrDigit(cs.charAt(i))) { + return false; + } + } + return true; + } + + // https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java#L3774-L3785 + public static boolean isNumeric(final CharSequence cs) { + if (isEmpty(cs)) { + return false; + } + final int sz = cs.length(); + for (int i = 0; i < sz; i++) { + if (!Character.isDigit(cs.charAt(i))) { + return false; + } + } + return true; + } + + // https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java#L1899-L1910 + public static boolean equals(final CharSequence cs1, final CharSequence cs2, final boolean ignoreCase) { // make ignore case a parameter + if (cs1 == cs2) { + return true; + } + if (cs1 == null || cs2 == null) { + return false; + } + if (cs1.length() != cs2.length()) { + return false; + } + return CharSequenceUtils.regionMatches(cs1, ignoreCase, 0, cs2, 0, cs1.length()); // make ignore case a parameter + } + + // https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java#L7990-L8000 + public static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) { // private -> public + if (str == null || prefix == null) { + return str == prefix; + } + // Get length once instead of twice in the unlikely case that it changes. + final int preLen = prefix.length(); + if (preLen > str.length()) { + return false; + } + return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0, preLen); + } + + // https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/StringUtils.java#L1702-L1711 + public static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) { // private -> public + if (str == null || suffix == null) { + return str == suffix; + } + if (suffix.length() > str.length()) { + return false; + } + final int strOffset = str.length() - suffix.length(); + return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length()); + } +} |
