From fc23da434376b392a6b587503cd9b0b9a0fbf3be Mon Sep 17 00:00:00 2001 From: Florian CUNY Date: Sat, 21 Dec 2019 14:23:32 +0100 Subject: [PATCH] Added Util#isInteger() and made commands use it for more reliability --- .../admin/deaths/AdminDeathsAddCommand.java | 3 +- .../deaths/AdminDeathsRemoveCommand.java | 3 +- .../admin/deaths/AdminDeathsSetCommand.java | 3 +- .../admin/range/AdminRangeAddCommand.java | 3 +- .../admin/range/AdminRangeRemoveCommand.java | 3 +- .../admin/range/AdminRangeSetCommand.java | 4 +- .../admin/resets/AdminResetsAddCommand.java | 3 +- .../resets/AdminResetsRemoveCommand.java | 3 +- .../admin/resets/AdminResetsSetCommand.java | 3 +- .../world/bentobox/bentobox/util/Util.java | 61 +++++++++++++++++++ .../admin/range/AdminRangeSetCommandTest.java | 1 - .../bentobox/bentobox/util/UtilTest.java | 51 ++++++++++++---- 12 files changed, 119 insertions(+), 22 deletions(-) diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsAddCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsAddCommand.java index 9930f7b79..fcfd342a5 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsAddCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsAddCommand.java @@ -5,6 +5,7 @@ import org.eclipse.jdt.annotation.NonNull; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.util.Util; import java.util.List; import java.util.UUID; @@ -35,7 +36,7 @@ public class AdminDeathsAddCommand extends CompositeCommand { UUID target = getPlayers().getUUID(args.get(0)); if (target == null) { user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); - } else if (!NumberUtils.isNumber(args.get(1)) || Integer.valueOf(args.get(1)) < 0) { + } else if (!Util.isInteger(args.get(1), true) || Integer.valueOf(args.get(1)) < 0) { user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1)); } else { getPlayers().setDeaths(getWorld(), target, getPlayers().getDeaths(getWorld(), target) + Integer.valueOf(args.get(1))); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsRemoveCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsRemoveCommand.java index 3e759773c..383944f4a 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsRemoveCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsRemoveCommand.java @@ -5,6 +5,7 @@ import org.eclipse.jdt.annotation.NonNull; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.util.Util; import java.util.List; import java.util.UUID; @@ -35,7 +36,7 @@ public class AdminDeathsRemoveCommand extends CompositeCommand { UUID target = getPlayers().getUUID(args.get(0)); if (target == null) { user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); - } else if (!NumberUtils.isNumber(args.get(1)) || Integer.valueOf(args.get(1)) < 0) { + } else if (!Util.isInteger(args.get(1), true) || Integer.valueOf(args.get(1)) < 0) { user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1)); } else { // Make sure it cannot go under 0. diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsSetCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsSetCommand.java index 041fbc4a3..9151a5075 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsSetCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/deaths/AdminDeathsSetCommand.java @@ -9,6 +9,7 @@ import org.eclipse.jdt.annotation.NonNull; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.util.Util; /** * @author Poslovitch @@ -35,7 +36,7 @@ public class AdminDeathsSetCommand extends CompositeCommand { UUID target = getPlayers().getUUID(args.get(0)); if (target == null) { user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); - } else if (!NumberUtils.isNumber(args.get(1)) || Integer.valueOf(args.get(1)) < 0) { + } else if (!Util.isInteger(args.get(1), true) || Integer.valueOf(args.get(1)) < 0) { user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1)); } else { getPlayers().setDeaths(getWorld(), target, Integer.valueOf(args.get(1))); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeAddCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeAddCommand.java index 0a93e0a51..3bbeea0d3 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeAddCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeAddCommand.java @@ -6,6 +6,7 @@ import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.util.Util; import java.util.List; import java.util.UUID; @@ -44,7 +45,7 @@ public class AdminRangeAddCommand extends CompositeCommand { return false; } - if (!NumberUtils.isNumber(args.get(1)) || Integer.valueOf(args.get(1)) < 0) { + if (!Util.isInteger(args.get(1), true) || Integer.valueOf(args.get(1)) < 0) { user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1)); return false; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeRemoveCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeRemoveCommand.java index 04c8ec772..df404fc3a 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeRemoveCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeRemoveCommand.java @@ -6,6 +6,7 @@ import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.util.Util; import java.util.List; import java.util.UUID; @@ -44,7 +45,7 @@ public class AdminRangeRemoveCommand extends CompositeCommand { return false; } - if (!NumberUtils.isNumber(args.get(1)) || Integer.valueOf(args.get(1)) < 0) { + if (!Util.isInteger(args.get(1), true) || Integer.valueOf(args.get(1)) < 0) { user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1)); return false; } diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommand.java index b04bc5ed7..2bb89b9be 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommand.java @@ -45,11 +45,11 @@ public class AdminRangeSetCommand extends CompositeCommand { } // Get new range - if (!NumberUtils.isNumber(args.get(1)) || Integer.valueOf(args.get(1)) < 0) { + if (!Util.isInteger(args.get(1), true) || Integer.valueOf(args.get(1)) < 0) { user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1)); return false; } - int range = Integer.parseInt(args.get(1)); + int range = Integer.valueOf(args.get(1)); // Get island Island island = getIslands().getIsland(getWorld(), targetUUID); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsAddCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsAddCommand.java index 3884da0fb..ba915748d 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsAddCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsAddCommand.java @@ -5,6 +5,7 @@ import org.eclipse.jdt.annotation.NonNull; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.util.Util; import java.util.List; import java.util.UUID; @@ -35,7 +36,7 @@ public class AdminResetsAddCommand extends CompositeCommand { UUID target = getPlayers().getUUID(args.get(0)); if (target == null) { user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); - } else if (!NumberUtils.isNumber(args.get(1)) || Integer.valueOf(args.get(1)) < 0) { + } else if (!Util.isInteger(args.get(1), true) || Integer.valueOf(args.get(1)) < 0) { user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1)); } else { getPlayers().setResets(getWorld(), target, getPlayers().getResets(getWorld(), target) + Integer.valueOf(args.get(1))); diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsRemoveCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsRemoveCommand.java index 24eb111d2..fa61b7f1e 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsRemoveCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsRemoveCommand.java @@ -5,6 +5,7 @@ import org.eclipse.jdt.annotation.NonNull; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.util.Util; import java.util.List; import java.util.UUID; @@ -35,7 +36,7 @@ public class AdminResetsRemoveCommand extends CompositeCommand { UUID target = getPlayers().getUUID(args.get(0)); if (target == null) { user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); - } else if (!NumberUtils.isNumber(args.get(1)) || Integer.valueOf(args.get(1)) < 0) { + } else if (!Util.isInteger(args.get(1), true) || Integer.valueOf(args.get(1)) < 0) { user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1)); } else { // Make sure it cannot go under 0. diff --git a/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsSetCommand.java b/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsSetCommand.java index 449c38ee8..3f4a1075c 100644 --- a/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsSetCommand.java +++ b/src/main/java/world/bentobox/bentobox/api/commands/admin/resets/AdminResetsSetCommand.java @@ -8,6 +8,7 @@ import org.apache.commons.lang.math.NumberUtils; import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.user.User; +import world.bentobox.bentobox.util.Util; public class AdminResetsSetCommand extends CompositeCommand { @@ -31,7 +32,7 @@ public class AdminResetsSetCommand extends CompositeCommand { UUID target = getPlayers().getUUID(args.get(0)); if (target == null) { user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); - } else if (!NumberUtils.isNumber(args.get(1)) || Integer.valueOf(args.get(1)) <= 0) { + } else if (!Util.isInteger(args.get(1), true) || Integer.valueOf(args.get(1)) <= 0) { user.sendMessage("general.errors.must-be-positive-number", TextVariables.NUMBER, args.get(1)); } else { getPlayers().setResets(getWorld(), target, Integer.valueOf(args.get(1))); diff --git a/src/main/java/world/bentobox/bentobox/util/Util.java b/src/main/java/world/bentobox/bentobox/util/Util.java index 24d6da58a..ea0bfcc35 100644 --- a/src/main/java/world/bentobox/bentobox/util/Util.java +++ b/src/main/java/world/bentobox/bentobox/util/Util.java @@ -532,4 +532,65 @@ public class Util { textToStrip = textToStrip.replaceAll("(" + ChatColor.COLOR_CHAR + ".)[\\s]", "$1"); return textToStrip; } + + /** + * Returns whether the input is an integer or not. + * @param nbr the input. + * @param parse whether the input should be checked to ensure it can be parsed as an Integer without throwing an exception. + * @return {@code true} if the input is an integer, {@code false} otherwise. + * @since 1.10.0 + */ + public static boolean isInteger(@NonNull String nbr, boolean parse) { + // Original code from Jonas Klemming on StackOverflow (https://stackoverflow.com/q/237159). + // I slightly refined it to catch more edge cases. + // It is a faster alternative to catch malformed strings than the NumberFormatException. + if (nbr == null) { + return false; + } + int length = nbr.length(); + if (length == 0) { + return false; + } + int i = 0; + if (nbr.charAt(0) == '-' || nbr.charAt(0) == '+') { + if (length == 1) { + return false; + } + i = 1; + } + boolean trailingDot = false; + for (; i < length; i++) { + char c = nbr.charAt(i); + if (trailingDot && c != '0') { + // We only accept 0's after a trailing dot. + return false; + } + if (c == '.') { + if (i == length - 1) { + // We're at the end of the integer, so it's okay + return true; + } else { + // we will need to make sure there is nothing else but 0's after the dot. + trailingDot = true; + continue; + } + } else if (!trailingDot && (c < '0' || c > '9')) { + return false; + } + } + + // these tests above should have caught most likely issues + // We now need to make sure parsing the input as an Integer won't cause issues + if (parse) { + try { + Integer.parseInt(nbr); // NOSONAR we don't care about the result of this operation + return true; + } catch (NumberFormatException e) { + return false; + } + } + + // Everything's green! + return true; + } } diff --git a/src/test/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommandTest.java b/src/test/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommandTest.java index e48840685..917d731af 100644 --- a/src/test/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommandTest.java +++ b/src/test/java/world/bentobox/bentobox/api/commands/admin/range/AdminRangeSetCommandTest.java @@ -231,7 +231,6 @@ public class AdminRangeSetCommandTest { * Test method for {@link world.bentobox.bentobox.api.commands.admin.range.AdminRangeSetCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. */ @Test() - @Ignore("will fix later") public void testExecuteDoubleNumber() { when(pm.getUUID(Mockito.anyString())).thenReturn(uuid); AdminRangeSetCommand arc = new AdminRangeSetCommand(ac); diff --git a/src/test/java/world/bentobox/bentobox/util/UtilTest.java b/src/test/java/world/bentobox/bentobox/util/UtilTest.java index 36ef1388d..a3d304941 100644 --- a/src/test/java/world/bentobox/bentobox/util/UtilTest.java +++ b/src/test/java/world/bentobox/bentobox/util/UtilTest.java @@ -1,6 +1,3 @@ -/** - * - */ package world.bentobox.bentobox.util; import static org.junit.Assert.assertEquals; @@ -156,14 +153,6 @@ public class UtilTest { //fail("Not yet implemented"); // TODO } - /** - * Test method for {@link world.bentobox.bentobox.util.Util#getPermValue(org.bukkit.entity.Player, java.lang.String, int)}. - */ - @Test - public void testGetPermValue() { - //fail("Not yet implemented"); // TODO - } - /** * Test method for {@link world.bentobox.bentobox.util.Util#xyz(org.bukkit.util.Vector)}. */ @@ -223,4 +212,44 @@ public class UtilTest { //fail("Not yet implemented"); // TODO } + @Test + public void testIsIntegerInputNotDigits() { + assertFalse(Util.isInteger("abdjeodl", false)); + assertFalse(Util.isInteger(" ./;. .!^", false)); + } + + @Test + public void testIsIntegerInputEmpty() { + assertFalse(Util.isInteger("", false)); + } + + @Test + public void testIsIntegerInputNegativeInteger() { + assertTrue(Util.isInteger("-2", false)); + assertTrue(Util.isInteger("-2", true)); + } + + @Test + public void testIsIntegerInputPi() { + assertFalse(Util.isInteger("3.1415", false)); + assertFalse(Util.isInteger("3.1415", true)); + } + + @Test + public void testIsIntegerInputOK() { + assertTrue(Util.isInteger("0", true)); + assertTrue(Util.isInteger("+1", true)); + assertTrue(Util.isInteger("-0", true)); + assertTrue(Util.isInteger("14", true)); + } + + @Test + public void testIsIntegerInputTrailingDot() { + assertTrue(Util.isInteger("1.", true)); + assertTrue(Util.isInteger("1.", false)); + assertTrue(Util.isInteger("1.000000", false)); + // assertTrue(Util.isInteger("1.000000", true)); + // For some reason, Integer#parseInt() does not support this... + } + }