Merge ListUtil into StringUtil; refactor HelpSyntaxHelper + create test

The HelpSyntaxHelper had suppressed warnings for string concatenation within StringBuilder - the point of the StringBuilder is that it is faster when you use it to concatenate many elements. If you still use string concatenation with + within these calls it beats the purpose.
(cherry picked from commit bb00be2)
This commit is contained in:
ljacqu 2015-11-21 11:57:04 +01:00
parent 115680a363
commit 4702a1b82d
6 changed files with 220 additions and 102 deletions

View File

@ -3,7 +3,6 @@ package fr.xephi.authme.command;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import fr.xephi.authme.util.ListUtils;
import fr.xephi.authme.util.StringUtils; import fr.xephi.authme.util.StringUtils;
/** /**
@ -165,8 +164,8 @@ public class CommandParts {
* *
* @param other The other reference. * @param other The other reference.
* *
* @return The result from zero to above. A negative number will be returned on error.
* @return The result from zero to above. A negative number will be returned on error. */ */
public double getDifference(CommandParts other) { public double getDifference(CommandParts other) {
return getDifference(other, false); return getDifference(other, false);
} }
@ -177,8 +176,8 @@ public class CommandParts {
* @param other The other reference. * @param other The other reference.
* @param fullCompare True to compare the full references as far as the range reaches. * @param fullCompare True to compare the full references as far as the range reaches.
* *
* @return The result from zero to above. A negative number will be returned on error.
* @return The result from zero to above. A negative number will be returned on error. */ */
public double getDifference(CommandParts other, boolean fullCompare) { public double getDifference(CommandParts other, boolean fullCompare) {
// Make sure the other reference is correct // Make sure the other reference is correct
if(other == null) if(other == null)
@ -196,10 +195,10 @@ public class CommandParts {
/** /**
* Convert the parts to a string. * Convert the parts to a string.
* *
* @return The part as a string.
* @return The part as a string. */ */
@Override @Override
public String toString() { public String toString() {
return ListUtils.implode(this.parts, " "); return StringUtils.join(" ", this.parts);
} }
} }

View File

@ -1,13 +1,15 @@
package fr.xephi.authme.command.help; package fr.xephi.authme.command.help;
import fr.xephi.authme.util.StringUtils;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import fr.xephi.authme.command.CommandArgumentDescription; import fr.xephi.authme.command.CommandArgumentDescription;
import fr.xephi.authme.command.CommandDescription; import fr.xephi.authme.command.CommandDescription;
import fr.xephi.authme.command.CommandParts; import fr.xephi.authme.command.CommandParts;
import fr.xephi.authme.util.ListUtils;
/** /**
* Helper class for formatting a command's structure (name and arguments)
* for a Minecraft user.
*/ */
public final class HelpSyntaxHelper { public final class HelpSyntaxHelper {
@ -16,52 +18,63 @@ public final class HelpSyntaxHelper {
} }
/** /**
* Get the proper syntax for a command. * Get the formatted syntax for a command.
* *
* @param commandDescription The command to get the syntax for. * @param commandDescription The command to build the syntax for.
* @param commandReference The reference of the command. * @param commandReference The reference of the command.
* @param alternativeLabel The alternative label to use for this command syntax. * @param alternativeLabel The alternative label to use for this command syntax.
* @param highlight True to highlight the important parts of this command. * @param highlight True to highlight the important parts of this command.
* *
* @return The command with proper syntax. * @return The command with proper syntax.
*/ */
@SuppressWarnings("StringConcatenationInsideStringBufferAppend") public static String getCommandSyntax(CommandDescription commandDescription, CommandParts commandReference,
public static String getCommandSyntax(CommandDescription commandDescription, CommandParts commandReference, String alternativeLabel, boolean highlight) { String alternativeLabel, boolean highlight) {
// Create a string builder to build the command // Create a string builder with white color and prefixed slash
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder()
.append(ChatColor.WHITE)
// Set the color and prefix a slash .append("/");
sb.append(ChatColor.WHITE + "/");
// Get the help command reference, and the command label // Get the help command reference, and the command label
CommandParts helpCommandReference = commandDescription.getCommandReference(commandReference); CommandParts helpCommandReference = commandDescription.getCommandReference(commandReference);
final String parentCommand = (new CommandParts(helpCommandReference.getRange(0, helpCommandReference.getCount() - 1))).toString(); final String parentCommand = new CommandParts(
String commandLabel = helpCommandReference.get(helpCommandReference.getCount() - 1); helpCommandReference.getRange(0, helpCommandReference.getCount() - 1)).toString();
// Check whether the alternative label should be used // Check whether the alternative label should be used
if (alternativeLabel != null && alternativeLabel.trim().length() > 0) { String commandLabel;
if (StringUtils.isEmpty(alternativeLabel)) {
commandLabel = helpCommandReference.get(helpCommandReference.getCount() - 1);
} else {
commandLabel = alternativeLabel; commandLabel = alternativeLabel;
} }
// Show the important bit of the command, highlight this part if required // Show the important bit of the command, highlight this part if required
sb.append(ListUtils.implode(parentCommand, (highlight ? ChatColor.YELLOW + "" + ChatColor.BOLD : "") + commandLabel, " ")); sb.append(parentCommand)
if(highlight) .append(" ")
sb.append(ChatColor.YELLOW); .append(highlight ? ChatColor.YELLOW.toString() + ChatColor.BOLD : "")
.append(commandLabel);
// Add each command arguments if (highlight) {
for(CommandArgumentDescription arg : commandDescription.getArguments()) { sb.append(ChatColor.YELLOW);
// Add the argument as optional or non-optional argument }
if(!arg.isOptional())
sb.append(ChatColor.ITALIC + " <" + arg.getLabel() + ">"); // Add each command argument
else for (CommandArgumentDescription arg : commandDescription.getArguments()) {
sb.append(ChatColor.ITALIC + " [" + arg.getLabel() + "]"); sb.append(ChatColor.ITALIC).append(formatArgument(arg));
} }
// Add some dots if the command allows unlimited arguments // Add some dots if the command allows unlimited arguments
if(commandDescription.getMaximumArguments() < 0) if (commandDescription.getMaximumArguments() < 0) {
sb.append(ChatColor.ITALIC + " ..."); sb.append(ChatColor.ITALIC).append(" ...");
}
// Return the build command syntax // Return the build command syntax
return sb.toString(); return sb.toString();
} }
private static String formatArgument(CommandArgumentDescription argument) {
if (argument.isOptional()) {
return " [" + argument.getLabel() + "]";
}
return " <" + argument.getLabel() + ">";
}
} }

View File

@ -1,58 +0,0 @@
package fr.xephi.authme.util;
import java.util.ArrayList;
import java.util.List;
/**
*/
public class ListUtils {
/**
* Implode a list of elements into a single string, with a specified separator.
*
* @param elements The elements to implode.
* @param separator The separator to use.
*
* @return The result string. */
public static String implode(List<String> elements, String separator) {
// Create a string builder
StringBuilder sb = new StringBuilder();
// Append each element
for(String element : elements) {
// Make sure the element isn't empty
if(element.trim().length() == 0)
continue;
// Prefix the separator if it isn't the first element
if(sb.length() > 0)
sb.append(separator);
// Append the element
sb.append(element);
}
// Return the result
return sb.toString();
}
/**
* Implode two elements into a single string, with a specified separator.
*
* @param element The first element to implode.
* @param otherElement The second element to implode.
* @param separator The separator to use.
*
* @return The result string. */
public static String implode(String element, String otherElement, String separator) {
// Combine the lists
List<String> combined = new ArrayList<>();
combined.add(element);
combined.add(otherElement);
// Implode and return the result
return implode(combined, separator);
}
}

View File

@ -5,17 +5,18 @@ import net.ricecode.similarity.StringSimilarityService;
import net.ricecode.similarity.StringSimilarityServiceImpl; import net.ricecode.similarity.StringSimilarityServiceImpl;
/** /**
* Utility class for String operations.
*/ */
public class StringUtils { public class StringUtils {
/** /**
* Get the difference of two strings. * Get the difference of two strings.
* *
* @param first First string. * @param first First string
* @param second Second string. * @param second Second string
* *
* @return The difference value
* @return The difference value. */ */
public static double getDifference(String first, String second) { public static double getDifference(String first, String second) {
// Make sure the strings are valid. // Make sure the strings are valid.
if(first == null || second == null) if(first == null || second == null)
@ -27,22 +28,60 @@ public class StringUtils {
// Determine the difference value, return the result // Determine the difference value, return the result
return Math.abs(service.score(first, second) - 1.0); return Math.abs(service.score(first, second) - 1.0);
} }
/** /**
* Method containsAny. * Returns whether the given string contains any of the provided elements.
* @param str String *
* @param pieces String[] * @param str the string to analyze
* @param pieces the items to check the string for
* @return boolean */ *
* @return true if the string contains at least one of the items
*/
public static boolean containsAny(String str, String... pieces) { public static boolean containsAny(String str, String... pieces) {
if (str == null) { if (str == null) {
return false; return false;
} }
for (String piece : pieces) { for (String piece : pieces) {
if (str.contains(piece)) { if (piece != null && str.contains(piece)) {
return true; return true;
} }
} }
return false; return false;
} }
/**
* Null-safe method for checking whether a string is empty. Note that the string
* is trimmed, so this method also considers a string with whitespace as empty.
*
* @param str the string to verify
*
* @return true if the string is empty, false otherwise
*/
public static boolean isEmpty(String str) {
return str == null || str.trim().isEmpty();
}
/**
* Joins a list of elements into a single string with the specified delimiter.
*
* @param delimiter the delimiter to use
* @param elements the elements to join
*
* @return a new String that is composed of the elements separated by the delimiter
*/
public static String join(String delimiter, Iterable<String> elements) {
StringBuilder sb = new StringBuilder();
for (String element : elements) {
if (!isEmpty(element)) {
// Add the separator if it isn't the first element
if (sb.length() > 0) {
sb.append(delimiter);
}
sb.append(element);
}
}
return sb.toString();
}
} }

View File

@ -0,0 +1,38 @@
package fr.xephi.authme.command;
import org.junit.Test;
import java.util.Arrays;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* Test for {@link CommandParts}.
*/
public class CommandPartsTest {
@Test
public void shouldPrintPartsForStringRepresentation() {
// given
CommandParts parts = new CommandParts(Arrays.asList("some", "parts", "for", "test"));
// when
String str = parts.toString();
// then
assertThat(str, equalTo("some parts for test"));
}
@Test
public void shouldPrintEmptyStringForNoArguments() {
// given
CommandParts parts = new CommandParts();
// when
String str = parts.toString();
// then
assertThat(str, equalTo(""));
}
}

View File

@ -0,0 +1,87 @@
package fr.xephi.authme.util;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* Test for {@link StringUtils}.
*/
public class StringUtilsTest {
@Test
public void shouldFindContainedItem() {
// given
String text = "This is a test of containsAny()";
String piece = "test";
// when
boolean result = StringUtils.containsAny(text, "some", "words", "that", "do not", "exist", piece);
// then
assertThat(result, equalTo(true));
}
@Test
public void shouldReturnFalseIfNoneFound() {
// given
String text = "This is a test string";
// when
boolean result = StringUtils.containsAny(text, "some", "other", "words", null);
// then
assertThat(result, equalTo(false));
}
@Test
public void shouldReturnFalseForNullString() {
// given/when
boolean result = StringUtils.containsAny(null, "some", "words", "to", "check");
// then
assertThat(result, equalTo(false));
}
@Test
public void shouldCheckIsEmptyUtil() {
// Should be true for null/empty/whitespace
assertTrue(StringUtils.isEmpty(null));
assertTrue(StringUtils.isEmpty(""));
assertTrue(StringUtils.isEmpty(" \t"));
// Should be false if string has content
assertFalse(StringUtils.isEmpty("P"));
assertFalse(StringUtils.isEmpty(" test"));
}
@Test
public void shouldJoinString() {
// given
List<String> elements = Arrays.asList("test", "for", null, "join", "StringUtils");
// when
String result = StringUtils.join(", ", elements);
// then
assertThat(result, equalTo("test, for, join, StringUtils"));
}
@Test
public void shouldNotHaveDelimiter() {
// given
List<String> elements = Arrays.asList(" ", null, "\t", "hello", null);
// when
String result = StringUtils.join("-", elements);
// then
assertThat(result, equalTo("hello"));
}
}