TEXT-81: Add RandomStringGenerator (closes #36) add changes.xml entries for TEXT-81 and TEXT-36
fix checkstyle violations other minimal clean-up fix checkstyle Project: http://git-wip-us.apache.org/repos/asf/commons-text/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-text/commit/c72a24bc Tree: http://git-wip-us.apache.org/repos/asf/commons-text/tree/c72a24bc Diff: http://git-wip-us.apache.org/repos/asf/commons-text/diff/c72a24bc Branch: refs/heads/master Commit: c72a24bc24f2650a71bee0418b2ee3609f297cdc Parents: 8d14206 Author: Pascal Schumacher <pascalschumac...@gmx.net> Authored: Mon Apr 24 22:28:09 2017 +0200 Committer: Pascal Schumacher <pascalschumac...@gmx.net> Committed: Fri Apr 28 16:26:36 2017 +0200 ---------------------------------------------------------------------- src/changes/changes.xml | 2 + .../commons/text/RandomStringGenerator.java | 106 ++++++++----------- .../apache/commons/text/TextRandomProvider.java | 4 +- .../commons/text/RandomStringGeneratorTest.java | 66 ++++++------ 4 files changed, 82 insertions(+), 96 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-text/blob/c72a24bc/src/changes/changes.xml ---------------------------------------------------------------------- diff --git a/src/changes/changes.xml b/src/changes/changes.xml index cd59174..91067bb 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,6 +46,8 @@ The <action> type attribute can be add,update,fix,remove. <body> <release version="1.1" date="tbd" description="tbd"> + <action issue="TEXT-81" type="add" dev="pschumacher" dev="djones">Add RandomStringGenerator</action> + <action issue="TEXT-36" type="add" dev="pschumacher" due-to="Raymond DeCampo">RandomStringGenerator: allow users to provide source of randomness</action> <action issue="TEXT-76" type="fix" dev="kinow">Correct round issue in Jaro Winkler implementation</action> <action issue="TEXT-72" type="fix" dev="chtompki">Similar to LANG-1025, clirr fails site build.</action> </release> http://git-wip-us.apache.org/repos/asf/commons-text/blob/c72a24bc/src/main/java/org/apache/commons/text/RandomStringGenerator.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/text/RandomStringGenerator.java b/src/main/java/org/apache/commons/text/RandomStringGenerator.java index 7eb45d9..ab7fd9d 100644 --- a/src/main/java/org/apache/commons/text/RandomStringGenerator.java +++ b/src/main/java/org/apache/commons/text/RandomStringGenerator.java @@ -27,7 +27,12 @@ import java.util.concurrent.ThreadLocalRandom; * callers to define the properties of the generator. See the documentation for the * {@link Builder} class to see available properties. * </p> - * + * <pre> + * // Generates a 20 code point string, using only the letters a-z + * RandomStringGenerator generator = new RandomStringGenerator.Builder() + * .withinRange('a', 'z').build(); + * String randomLetters = generator.generate(20); + * </pre> * <pre> * // Using Apache Commons RNG for randomness * UniformRandomProvider rng = RandomSource.create(...); @@ -36,14 +41,12 @@ import java.util.concurrent.ThreadLocalRandom; * .withinRange('a', 'z') * .usingRandom(rng::nextInt) // uses Java 8 syntax * .build(); - * String random = generator.generate(20); + * String randomLetters = generator.generate(20); * </pre> - * * <p> * {@code RandomStringBuilder} instances are immutable and thread-safe. * </p> - * - * @since 1.0 + * @since 1.1 */ public final class RandomStringGenerator { @@ -52,10 +55,9 @@ public final class RandomStringGenerator { private final Set<CharacterPredicate> inclusivePredicates; private final TextRandomProvider random; - /** * Constructs the generator. - * + * * @param minimumCodePoint * smallest allowed code point (inclusive) * @param maximumCodePoint @@ -72,12 +74,11 @@ public final class RandomStringGenerator { this.inclusivePredicates = inclusivePredicates; this.random = random; } - + /** - * Generates a random number within a range, using a - * {@link ThreadLocalRandom} instance or the user-supplied source of - * randomness. - * + * Generates a random number within a range, using a {@link ThreadLocalRandom} instance + * or the user-supplied source of randomness. + * * @param minInclusive * the minimum value allowed * @param maxInclusive @@ -88,11 +89,9 @@ public final class RandomStringGenerator { if (random != null) { return random.nextInt(maxInclusive - minInclusive + 1) + minInclusive; } - return ThreadLocalRandom.current().nextInt(minInclusive, maxInclusive + 1); } - /** * <p> * Generates a random string, containing the specified number of code points. @@ -109,19 +108,17 @@ public final class RandomStringGenerator { * {@link Character} documentation to understand how Java stores Unicode * values. * </p> - * + * * @param length * the number of code points to generate * @return the generated string * @throws IllegalArgumentException * if {@code length < 0} - * @since 1.0 */ public String generate(final int length) { if (length == 0) { return ""; } - if (length < 0) { throw new IllegalArgumentException(String.format("Length %d is smaller than zero.", length)); } @@ -137,6 +134,7 @@ public final class RandomStringGenerator { case Character.PRIVATE_USE: case Character.SURROGATE: continue; + default: } if (inclusivePredicates != null) { @@ -159,52 +157,44 @@ public final class RandomStringGenerator { return builder.toString(); } - - + /** * <p>A builder for generating {@code RandomStringGenerator} instances.</p> * <p>The behaviour of a generator is controlled by properties set by this * builder. Each property has a default value, which can be overridden by * calling the methods defined in this class, prior to calling {@link #build()}.</p> - * + * * <p>All the property setting methods return the {@code Builder} instance to allow for method chaining.</p> - * + * * <p>The minimum and maximum code point values are defined using {@link #withinRange(int, int)}. The * default values are {@code 0} and {@link Character#MAX_CODE_POINT} respectively.</p> - * - * <p>The source of randomness can be set using {@link #usingRandom(TextRandomProvider) }, otherwise {@link ThreadLocalRandom} - * is used.</p> - * - * <p>The type of code points returned can be filtered using {@link #filteredBy(CharacterPredicate...)}, - * which defines a collection of - * tests that are applied to the randomly generated code points. The code points - * will only be included in the result if they pass at least one of the tests. + * + * <p>The source of randomness can be set using {@link #usingRandom(TextRandomProvider)}, + * otherwise {@link ThreadLocalRandom} is used.</p> + * + * <p>The type of code points returned can be filtered using {@link #filteredBy(CharacterPredicate...)}, + * which defines a collection of tests that are applied to the randomly generated code points. + * The code points will only be included in the result if they pass at least one of the tests. * Some commonly used predicates are provided by the {@link CharacterPredicates} enum.</p> - * + * * <p>This class is not thread safe.</p> - * @since 1.0 + * @since 1.1 */ public static class Builder implements org.apache.commons.text.Builder<RandomStringGenerator> { - + /** * The default maximum code point allowed: {@link Character#MAX_CODE_POINT} - * ({@value}) - * - * @since 1.0 + * ({@value}). */ public static final int DEFAULT_MAXIMUM_CODE_POINT = Character.MAX_CODE_POINT; - + /** - * The default string length produced by this builder: {@value} - * - * @since 1.0 + * The default string length produced by this builder: {@value}. */ public static final int DEFAULT_LENGTH = 0; /** - * The default minimum code point allowed: {@value} - * - * @since 1.0 + * The default minimum code point allowed: {@value}. */ public static final int DEFAULT_MINIMUM_CODE_POINT = 0; @@ -212,14 +202,13 @@ public final class RandomStringGenerator { private int maximumCodePoint = DEFAULT_MAXIMUM_CODE_POINT; private Set<CharacterPredicate> inclusivePredicates; private TextRandomProvider random; - - + /** * <p> - * Specifies the minimum and maximum code points allowed in the generated - * string. + * Specifies the minimum and maximum code points allowed in the + * generated string. * </p> - * + * * @param minimumCodePoint * the smallest code point allowed (inclusive) * @param maximumCodePoint @@ -232,15 +221,16 @@ public final class RandomStringGenerator { * if {@code minimumCodePoint < 0} * @throws IllegalArgumentException * if {@code minimumCodePoint > maximumCodePoint} - * @since 1.0 */ public Builder withinRange(final int minimumCodePoint, final int maximumCodePoint) { if (minimumCodePoint > maximumCodePoint) { throw new IllegalArgumentException(String.format( - "Minimum code point %d is larger than maximum code point %d", minimumCodePoint, maximumCodePoint)); + "Minimum code point %d is larger than maximum code point %d", + minimumCodePoint, maximumCodePoint)); } if (minimumCodePoint < 0) { - throw new IllegalArgumentException(String.format("Minimum code point %d is negative", minimumCodePoint)); + throw new IllegalArgumentException( + String.format("Minimum code point %d is negative", minimumCodePoint)); } if (maximumCodePoint > Character.MAX_CODE_POINT) { throw new IllegalArgumentException( @@ -251,23 +241,22 @@ public final class RandomStringGenerator { this.maximumCodePoint = maximumCodePoint; return this; } - + /** * <p> * Limits the characters in the generated string to those that match at * least one of the predicates supplied. * </p> - * + * * <p> * Passing {@code null} or an empty array to this method will revert to the * default behaviour of allowing any character. Multiple calls to this * method will replace the previously stored predicates. * </p> - * + * * @param predicates * the predicates, may be {@code null} or empty * @return {@code this}, to allow method chaining - * @since 1.0 */ public Builder filteredBy(final CharacterPredicate... predicates) { if (predicates == null || predicates.length == 0) { @@ -287,7 +276,7 @@ public final class RandomStringGenerator { return this; } - + /** * <p> * Overrides the default source of randomness. It is highly @@ -309,16 +298,15 @@ public final class RandomStringGenerator { * .build(); * } * </pre> - * + * * <p> * Passing {@code null} to this method will revert to the default source of * randomness. * </p> - * + * * @param random * the source of randomness, may be {@code null} * @return {@code this}, to allow method chaining - * @since 1.0 */ public Builder usingRandom(final TextRandomProvider random) { this.random = random; @@ -327,11 +315,11 @@ public final class RandomStringGenerator { /** * <p>Builds the {@code RandomStringGenerator} using the properties specified.</p> + * @return the configured {@code RandomStringGenerator} */ @Override public RandomStringGenerator build() { return new RandomStringGenerator(minimumCodePoint, maximumCodePoint, inclusivePredicates, random); } - } } http://git-wip-us.apache.org/repos/asf/commons-text/blob/c72a24bc/src/main/java/org/apache/commons/text/TextRandomProvider.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/text/TextRandomProvider.java b/src/main/java/org/apache/commons/text/TextRandomProvider.java index 4aecd72..98c5f2d 100644 --- a/src/main/java/org/apache/commons/text/TextRandomProvider.java +++ b/src/main/java/org/apache/commons/text/TextRandomProvider.java @@ -37,15 +37,15 @@ package org.apache.commons.text; * .build(); * } * </pre> + * @since 1.1 */ public interface TextRandomProvider { /** - * Generates an int value between 0 (inclusive) and the specified value + * Generates an int value between 0 (inclusive) and the specified value * (exclusive). * @param max Bound on the random number to be returned. Must be positive. * @return a random int value between 0 (inclusive) and n (exclusive). - * @throws IllegalArgumentException - if max is negative */ int nextInt(int max); } http://git-wip-us.apache.org/repos/asf/commons-text/blob/c72a24bc/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java b/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java index 0da2072..86537fa 100644 --- a/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java +++ b/src/test/java/org/apache/commons/text/RandomStringGeneratorTest.java @@ -25,10 +25,6 @@ import static org.junit.Assert.*; */ public class RandomStringGeneratorTest { - private static int codePointLength(String s) { - return s.codePointCount(0, s.length()); - } - private static final CharacterPredicate A_FILTER = new CharacterPredicate() { @Override public boolean test(int codePoint) { @@ -44,13 +40,17 @@ public class RandomStringGeneratorTest { }; @Test(expected = IllegalArgumentException.class) - public void testInvalidLength() throws Exception { + public void testInvalidLength() { RandomStringGenerator generator = new RandomStringGenerator.Builder().build(); generator.generate(-1); } + private static int codePointLength(String s) { + return s.codePointCount(0, s.length()); + } + @Test - public void testSetLength() throws Exception { + public void testSetLength() { final int length = 99; RandomStringGenerator generator = new RandomStringGenerator.Builder().build(); String str = generator.generate(length); @@ -58,34 +58,33 @@ public class RandomStringGeneratorTest { } @Test(expected = IllegalArgumentException.class) - public void testBadMinimumCodePoint() throws Exception { + public void testBadMinimumCodePoint() { new RandomStringGenerator.Builder().withinRange(-1, 1); } @Test(expected = IllegalArgumentException.class) - public void testBadMaximumCodePoint() throws Exception { + public void testBadMaximumCodePoint() { new RandomStringGenerator.Builder().withinRange(0, Character.MAX_CODE_POINT + 1); } @Test - public void testWithinRange() throws Exception { - final int length = 5000; - final int minimumCodePoint = 'a'; - final int maximumCodePoint = 'z'; - RandomStringGenerator generator = new RandomStringGenerator.Builder().withinRange(minimumCodePoint,maximumCodePoint).build(); - String str = generator.generate(length); - - int i = 0; - do { - int codePoint = str.codePointAt(i); - assertTrue(codePoint >= minimumCodePoint && codePoint <= maximumCodePoint); - i += Character.charCount(codePoint); - } while (i < str.length()); - - } + public void testWithinRange() { + final int length = 5000; + final int minimumCodePoint = 'a'; + final int maximumCodePoint = 'z'; + RandomStringGenerator generator = new RandomStringGenerator.Builder().withinRange(minimumCodePoint,maximumCodePoint).build(); + String str = generator.generate(length); + + int i = 0; + do { + int codePoint = str.codePointAt(i); + assertTrue(codePoint >= minimumCodePoint && codePoint <= maximumCodePoint); + i += Character.charCount(codePoint); + } while (i < str.length()); + } @Test - public void testNoLoneSurrogates() throws Exception { + public void testNoLoneSurrogates() { final int length = 5000; String str = new RandomStringGenerator.Builder().build().generate(length); @@ -111,10 +110,9 @@ public class RandomStringGeneratorTest { } @Test - public void testUsingRandom() throws Exception { + public void testUsingRandom() { final char testChar = 'a'; final TextRandomProvider testRandom = new TextRandomProvider() { - private static final long serialVersionUID = 1L; @Override public int nextInt(int n) { @@ -129,7 +127,7 @@ public class RandomStringGeneratorTest { } @Test - public void testMultipleFilters() throws Exception { + public void testMultipleFilters() { String str = new RandomStringGenerator.Builder().withinRange('a','d') .filteredBy(A_FILTER, B_FILTER).build().generate(5000); @@ -150,12 +148,11 @@ public class RandomStringGeneratorTest { } @Test - public void testNoPrivateCharacters() throws Exception { + public void testNoPrivateCharacters() { final int startOfPrivateBMPChars = 0xE000; // Request a string in an area of the Basic Multilingual Plane that is - // largely - // occupied by private characters + // largely occupied by private characters String str = new RandomStringGenerator.Builder().withinRange(startOfPrivateBMPChars, Character.MIN_SUPPLEMENTARY_CODE_POINT - 1).build().generate(5000); @@ -173,8 +170,7 @@ public class RandomStringGeneratorTest { } @Test - public void testRemoveFilters() throws Exception { - + public void testRemoveFilters() { RandomStringGenerator.Builder builder = new RandomStringGenerator.Builder().withinRange('a', 'z') .filteredBy(A_FILTER); @@ -192,7 +188,7 @@ public class RandomStringGeneratorTest { } @Test - public void testChangeOfFilter() throws Exception { + public void testChangeOfFilter() { RandomStringGenerator.Builder builder = new RandomStringGenerator.Builder().withinRange('a', 'z') .filteredBy(A_FILTER); String str = builder.filteredBy(B_FILTER).build().generate(100); @@ -201,9 +197,9 @@ public class RandomStringGeneratorTest { assertTrue(c == 'b'); } } - + @Test - public void testZeroLength() throws Exception { + public void testZeroLength() { RandomStringGenerator generator = new RandomStringGenerator.Builder().build(); assertEquals("", generator.generate(0)); }