From 0f431d01b1dd9d3fc806c1b0153668b657c08fd0 Mon Sep 17 00:00:00 2001 From: Fabio Lima Date: Sun, 18 Jul 2021 01:21:41 -0300 Subject: [PATCH] Add constructors in UlidFactory for random generators #12 New constructors: - public UlidFactory(Random random) { } - public UlidFactory(RandomGenerator randomGenerator) { } --- CHANGELOG.md | 13 ++++-- README.md | 19 ++++----- .../java/com/github/f4b6a3/ulid/Ulid.java | 13 ++++-- .../com/github/f4b6a3/ulid/UlidCreator.java | 26 ++---------- ...ltUlidFactory.java => DefaultFactory.java} | 32 ++++++++++++++- ...UlidFactory.java => MonotonicFactory.java} | 33 ++++++++++++++- .../f4b6a3/ulid/factory/UlidFactory.java | 34 +++++++-------- .../ulid/random/DefaultRandomGenerator.java | 41 ------------------- .../com/github/f4b6a3/ulid/TestSuite.java | 8 ++-- .../java/com/github/f4b6a3/ulid/UlidTest.java | 2 +- .../github/f4b6a3/ulid/UniquenessTest.java | 7 ++-- ...ctoryTest.java => DefaultFactoryTest.java} | 5 +-- ...oryTest.java => MonotonicFactoryTest.java} | 5 +-- 13 files changed, 121 insertions(+), 117 deletions(-) rename src/main/java/com/github/f4b6a3/ulid/factory/{DefaultUlidFactory.java => DefaultFactory.java} (70%) rename src/main/java/com/github/f4b6a3/ulid/factory/{MonotonicUlidFactory.java => MonotonicFactory.java} (74%) delete mode 100644 src/main/java/com/github/f4b6a3/ulid/random/DefaultRandomGenerator.java rename src/test/java/com/github/f4b6a3/ulid/factory/{DefaultUlidFactoryTest.java => DefaultFactoryTest.java} (92%) rename src/test/java/com/github/f4b6a3/ulid/factory/{MonotonicUlidFactoryTest.java => MonotonicFactoryTest.java} (92%) diff --git a/CHANGELOG.md b/CHANGELOG.md index e69d93a..abb1f03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,18 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -### Fixed +## [3.2.0] - 2021-07-17 -- Fixed typos in `CHANGELOG.md` +Simplified the use of `UlidFactory` with other random generators. + +### Added + +- Added constructors in `UlidFactory` for random generators. ## [3.1.1] - 2021-07-17 +Creates a module name be used in Java 9+. + ### Added - Added module name for Java 9+ @@ -233,7 +239,8 @@ Project created as an alternative Java implementation of [ULID spec](https://git - Added `LICENSE` - Added test cases -[unreleased]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.1.1...HEAD +[unreleased]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.2.0...HEAD +[3.1.0]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.1.1...ulid-creator-3.2.0 [3.1.0]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.1.0...ulid-creator-3.1.1 [3.1.0]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.0.1...ulid-creator-3.1.0 [3.0.1]: https://github.com/f4b6a3/ulid-creator/compare/ulid-creator-3.0.0...ulid-creator-3.0.1 diff --git a/README.md b/README.md index a54f8b8..a989177 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Add these lines to your `pom.xml`. com.github.f4b6a3 ulid-creator - 3.1.1 + 3.2.0 ``` See more options in [maven.org](https://search.maven.org/artifact/com.github.f4b6a3/ulid-creator). @@ -194,22 +194,20 @@ byte[] random = ulid.getRandom(); // 10 bytes (80 bits) byte[] random = Ulid.getRandom("0123456789ABCDEFGHJKMNPQRS"); // 10 bytes (80 bits) ``` -Use a `UlidFactory` instance with `java.util.Random` to generate ULIDs: +Use a `UlidFactory` with `java.util.Random`: ```java -Random random = new Random(); -UlidFactory factory = UlidCreator.getDefaultFactory().withRandomGenerator(random::nextBytes); - +// use a `Random` instance +UlidFactory factory = new DefaultFactory(new Random()); Ulid ulid = factory.create(); ``` -Use a `UlidFactory` instance with any random generator you like(*) to generate ULIDs: +Use a `UlidFactory` with a random generator of your choice: ```java +// use a method of any RNG with this signature: `void nextBytes(byte[])` import com.github.niceguy.random.AwesomeRandom; // a hypothetical RNG -AwesomeRandom awesomeRandom = new AwesomeRandom(); -UlidFactory factory = UlidCreator.getDefaultFactory().withRandomGenerator(awesomeRandom::nextBytes); - +UlidFactory factory = new DefaultFactory(new AwesomeRandom()::nextBytes); Ulid ulid = factory.create(); ``` @@ -244,5 +242,6 @@ See: [uuid-creator-benchmark](https://github.com/fabiolimace/uuid-creator-benchm Other generators ------------------------------------------- * [UUID Creator](https://github.com/f4b6a3/uuid-creator): for generating UUIDs -* [TSID Creator](https://github.com/f4b6a3/tsid-creator): for generating Time Sortable IDs +* [TSID Creator](https://github.com/f4b6a3/tsid-creator): for generating TSIDs +* [KSUID Creator](https://github.com/f4b6a3/ksuid-creator): for generating KSUIDs diff --git a/src/main/java/com/github/f4b6a3/ulid/Ulid.java b/src/main/java/com/github/f4b6a3/ulid/Ulid.java index d2285e1..6673b46 100644 --- a/src/main/java/com/github/f4b6a3/ulid/Ulid.java +++ b/src/main/java/com/github/f4b6a3/ulid/Ulid.java @@ -365,7 +365,8 @@ public final class Ulid implements Serializable, Comparable { * The output string is 26 characters long and contains only characters from * Crockford's base 32 alphabet. * - * It is at least twice as fast as {@code Ulid.toString().toLowerCase()}. + * It is a shorthand at least twice as fast as + * {@code Ulid.toString().toLowerCase()}. * * See: https://www.crockford.com/base32.html * @@ -542,7 +543,7 @@ public final class Ulid implements Serializable, Comparable { bytes[0x2] = (byte) (random0 >>> 16); bytes[0x3] = (byte) (random0 >>> 8); bytes[0x4] = (byte) (random0); - + bytes[0x5] = (byte) (random1 >>> 32); bytes[0x6] = (byte) (random1 >>> 24); bytes[0x7] = (byte) (random1 >>> 16); @@ -619,7 +620,13 @@ public final class Ulid implements Serializable, Comparable { /** * Converts the ULID into a canonical string in upper case. * - * It is the same as {@code Ulid.toUpperCase()}. + * The output string is 26 characters long and contains only characters from + * Crockford's base 32 alphabet. + * + * For lower case string, use the shorthand {@code Ulid#toLowerCase()}, instead + * of {@code Ulid#toString()#toLowerCase()}. + * + * See: https://www.crockford.com/base32.html * * @return a ULID string */ diff --git a/src/main/java/com/github/f4b6a3/ulid/UlidCreator.java b/src/main/java/com/github/f4b6a3/ulid/UlidCreator.java index f5ba04c..fbfdd71 100644 --- a/src/main/java/com/github/f4b6a3/ulid/UlidCreator.java +++ b/src/main/java/com/github/f4b6a3/ulid/UlidCreator.java @@ -24,8 +24,8 @@ package com.github.f4b6a3.ulid; -import com.github.f4b6a3.ulid.factory.DefaultUlidFactory; -import com.github.f4b6a3.ulid.factory.MonotonicUlidFactory; +import com.github.f4b6a3.ulid.factory.DefaultFactory; +import com.github.f4b6a3.ulid.factory.MonotonicFactory; import com.github.f4b6a3.ulid.factory.UlidFactory; /** @@ -92,29 +92,11 @@ public final class UlidCreator { return MonotonicFactoryHolder.INSTANCE.create(time); } - /** - * Returns an instance of the Default ULID factory. - * - * @return a ULID factory - */ - public static UlidFactory getDefaultFactory() { - return new DefaultUlidFactory(); - } - - /** - * Returns an instance of the Monotonic ULID factory. - * - * @return a ULID factory - */ - public static UlidFactory getMonotonicFactory() { - return new MonotonicUlidFactory(); - } - private static class DefaultFactoryHolder { - static final UlidFactory INSTANCE = getDefaultFactory(); + static final UlidFactory INSTANCE = new DefaultFactory(); } private static class MonotonicFactoryHolder { - static final UlidFactory INSTANCE = getMonotonicFactory(); + static final UlidFactory INSTANCE = new MonotonicFactory(); } } diff --git a/src/main/java/com/github/f4b6a3/ulid/factory/DefaultUlidFactory.java b/src/main/java/com/github/f4b6a3/ulid/factory/DefaultFactory.java similarity index 70% rename from src/main/java/com/github/f4b6a3/ulid/factory/DefaultUlidFactory.java rename to src/main/java/com/github/f4b6a3/ulid/factory/DefaultFactory.java index f3c28d9..12bf885 100644 --- a/src/main/java/com/github/f4b6a3/ulid/factory/DefaultUlidFactory.java +++ b/src/main/java/com/github/f4b6a3/ulid/factory/DefaultFactory.java @@ -24,16 +24,44 @@ package com.github.f4b6a3.ulid.factory; +import java.util.Random; + import com.github.f4b6a3.ulid.Ulid; +import com.github.f4b6a3.ulid.random.RandomGenerator; /** - * Factory that generates default ULIDs. + * Factory that generates ULIDs. * * The random component is always reset to a new random value. * * The maximum ULIDs that can be generated per millisecond is 2^80. */ -public class DefaultUlidFactory extends UlidFactory { +public class DefaultFactory extends UlidFactory { + + /** + * Use the default {@link java.security.SecureRandom}. + */ + public DefaultFactory() { + super(); + } + + /** + * Use a random generator that inherits from {@link Random}. + * + * @param random a {@link Random} instance + */ + public DefaultFactory(Random random) { + this(random::nextBytes); + } + + /** + * Use a random generator that inherits from {@link RandomGenerator}. + * + * @param randomGenerator a {@link RandomGenerator} instance + */ + public DefaultFactory(RandomGenerator randomGenerator) { + super(randomGenerator); + } /** * Returns a ULID. diff --git a/src/main/java/com/github/f4b6a3/ulid/factory/MonotonicUlidFactory.java b/src/main/java/com/github/f4b6a3/ulid/factory/MonotonicFactory.java similarity index 74% rename from src/main/java/com/github/f4b6a3/ulid/factory/MonotonicUlidFactory.java rename to src/main/java/com/github/f4b6a3/ulid/factory/MonotonicFactory.java index 70fe807..a708f1b 100644 --- a/src/main/java/com/github/f4b6a3/ulid/factory/MonotonicUlidFactory.java +++ b/src/main/java/com/github/f4b6a3/ulid/factory/MonotonicFactory.java @@ -24,23 +24,52 @@ package com.github.f4b6a3.ulid.factory; +import java.util.Random; + import com.github.f4b6a3.ulid.Ulid; +import com.github.f4b6a3.ulid.random.RandomGenerator; /** * Factory that generates Monotonic ULIDs. * - * The random component is reset to a new value every time the millisecond changes. + * The random component is reset to a new value every time the millisecond + * changes. * * If more than one ULID is generated within the same millisecond, the random * component is incremented by one. * * The maximum ULIDs that can be generated per millisecond is 2^80. */ -public final class MonotonicUlidFactory extends UlidFactory { +public final class MonotonicFactory extends UlidFactory { private long lastTime = -1; private Ulid lastUlid = null; + /** + * Use the default {@link java.security.SecureRandom}. + */ + public MonotonicFactory() { + super(); + } + + /** + * Use a random generator that inherits from {@link Random}. + * + * @param random a {@link Random} instance + */ + public MonotonicFactory(Random random) { + this(random::nextBytes); + } + + /** + * Use a random generator that inherits from {@link RandomGenerator}. + * + * @param randomGenerator a {@link RandomGenerator} instance + */ + public MonotonicFactory(RandomGenerator randomGenerator) { + super(randomGenerator); + } + /** * Returns a ULID. * diff --git a/src/main/java/com/github/f4b6a3/ulid/factory/UlidFactory.java b/src/main/java/com/github/f4b6a3/ulid/factory/UlidFactory.java index dda581e..b3f239a 100644 --- a/src/main/java/com/github/f4b6a3/ulid/factory/UlidFactory.java +++ b/src/main/java/com/github/f4b6a3/ulid/factory/UlidFactory.java @@ -24,10 +24,9 @@ package com.github.f4b6a3.ulid.factory; -import java.util.Random; +import java.security.SecureRandom; import com.github.f4b6a3.ulid.Ulid; -import com.github.f4b6a3.ulid.random.DefaultRandomGenerator; import com.github.f4b6a3.ulid.random.RandomGenerator; /** @@ -39,8 +38,20 @@ public abstract class UlidFactory { protected RandomGenerator randomGenerator; + /** + * Use the default {@link java.security.SecureRandom}. + */ public UlidFactory() { - this.randomGenerator = new DefaultRandomGenerator(); + this(new SecureRandom()::nextBytes); + } + + /** + * Use a random generator that inherits from {@link RandomGenerator}. + * + * @param randomGenerator a {@link RandomGenerator} instance + */ + public UlidFactory(RandomGenerator randomGenerator) { + this.randomGenerator = randomGenerator; } /** @@ -61,21 +72,4 @@ public abstract class UlidFactory { * @return a ULID */ public abstract Ulid create(final long time); - - /** - * Replaces the default random generator with another. - * - * The default random generator uses {@link java.security.SecureRandom}. - * - * See {@link Random}. - * - * @param the type parameter - * @param randomGenerator a random generator - * @return {@link UlidFactory} - */ - @SuppressWarnings("unchecked") - public synchronized T withRandomGenerator(RandomGenerator randomGenerator) { - this.randomGenerator = randomGenerator; - return (T) this; - } } diff --git a/src/main/java/com/github/f4b6a3/ulid/random/DefaultRandomGenerator.java b/src/main/java/com/github/f4b6a3/ulid/random/DefaultRandomGenerator.java deleted file mode 100644 index 0f082b8..0000000 --- a/src/main/java/com/github/f4b6a3/ulid/random/DefaultRandomGenerator.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2018-2020 Fabio Lima - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.github.f4b6a3.ulid.random; - -import java.security.SecureRandom; -import java.util.Random; - -/** - * It uses an instance of {@link java.security.SecureRandom}. - */ -public final class DefaultRandomGenerator implements RandomGenerator { - - private static final Random SECURE_RANDOM = new SecureRandom(); - - @Override - public void nextBytes(byte[] bytes) { - SECURE_RANDOM.nextBytes(bytes); - } -} diff --git a/src/test/java/com/github/f4b6a3/ulid/TestSuite.java b/src/test/java/com/github/f4b6a3/ulid/TestSuite.java index b51f9ce..b6de9b8 100644 --- a/src/test/java/com/github/f4b6a3/ulid/TestSuite.java +++ b/src/test/java/com/github/f4b6a3/ulid/TestSuite.java @@ -3,13 +3,13 @@ package com.github.f4b6a3.ulid; import org.junit.runner.RunWith; import org.junit.runners.Suite; -import com.github.f4b6a3.ulid.factory.DefaultUlidFactoryTest; -import com.github.f4b6a3.ulid.factory.MonotonicUlidFactoryTest; +import com.github.f4b6a3.ulid.factory.DefaultFactoryTest; +import com.github.f4b6a3.ulid.factory.MonotonicFactoryTest; @RunWith(Suite.class) @Suite.SuiteClasses({ - MonotonicUlidFactoryTest.class, - DefaultUlidFactoryTest.class, + MonotonicFactoryTest.class, + DefaultFactoryTest.class, UlidTest.class, }) diff --git a/src/test/java/com/github/f4b6a3/ulid/UlidTest.java b/src/test/java/com/github/f4b6a3/ulid/UlidTest.java index 9a3fd19..e305855 100644 --- a/src/test/java/com/github/f4b6a3/ulid/UlidTest.java +++ b/src/test/java/com/github/f4b6a3/ulid/UlidTest.java @@ -71,7 +71,7 @@ public class UlidTest { } try { - long time = 0x1000000000000000L; // negative number + long time = 0x8000000000000000L; // negative number byte[] bytes = new byte[Ulid.RANDOM_BYTES_LENGTH]; new Ulid(time, bytes); fail("Should throw an exception"); diff --git a/src/test/java/com/github/f4b6a3/ulid/UniquenessTest.java b/src/test/java/com/github/f4b6a3/ulid/UniquenessTest.java index 41a25a5..8616799 100644 --- a/src/test/java/com/github/f4b6a3/ulid/UniquenessTest.java +++ b/src/test/java/com/github/f4b6a3/ulid/UniquenessTest.java @@ -1,7 +1,9 @@ package com.github.f4b6a3.ulid; import java.util.HashSet; -import com.github.f4b6a3.ulid.UlidCreator; +import java.util.Random; + +import com.github.f4b6a3.ulid.factory.MonotonicFactory; import com.github.f4b6a3.ulid.factory.UlidFactory; /** @@ -117,8 +119,7 @@ public class UniquenessTest { } public static void execute(boolean verbose, int threadCount, int requestCount) { - UlidFactory factory = UlidCreator.getMonotonicFactory(); - + UlidFactory factory = new MonotonicFactory(new Random()); UniquenessTest test = new UniquenessTest(threadCount, requestCount, factory, verbose); test.start(); } diff --git a/src/test/java/com/github/f4b6a3/ulid/factory/DefaultUlidFactoryTest.java b/src/test/java/com/github/f4b6a3/ulid/factory/DefaultFactoryTest.java similarity index 92% rename from src/test/java/com/github/f4b6a3/ulid/factory/DefaultUlidFactoryTest.java rename to src/test/java/com/github/f4b6a3/ulid/factory/DefaultFactoryTest.java index f9765f2..5a0ce24 100644 --- a/src/test/java/com/github/f4b6a3/ulid/factory/DefaultUlidFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/ulid/factory/DefaultFactoryTest.java @@ -11,7 +11,7 @@ import static org.junit.Assert.*; import java.util.HashSet; import java.util.Random; -public class DefaultUlidFactoryTest extends UlidFactoryTest { +public class DefaultFactoryTest extends UlidFactoryTest { @Test public void testGetUlid() { @@ -67,8 +67,7 @@ public class DefaultUlidFactoryTest extends UlidFactoryTest { // Instantiate and start many threads for (int i = 0; i < THREAD_TOTAL; i++) { - Random random = new Random(); - UlidFactory factory = UlidCreator.getDefaultFactory().withRandomGenerator(random::nextBytes); + UlidFactory factory = new DefaultFactory(new Random()); threads[i] = new TestThread(factory, DEFAULT_LOOP_MAX); threads[i].start(); } diff --git a/src/test/java/com/github/f4b6a3/ulid/factory/MonotonicUlidFactoryTest.java b/src/test/java/com/github/f4b6a3/ulid/factory/MonotonicFactoryTest.java similarity index 92% rename from src/test/java/com/github/f4b6a3/ulid/factory/MonotonicUlidFactoryTest.java rename to src/test/java/com/github/f4b6a3/ulid/factory/MonotonicFactoryTest.java index 45443ae..47fd2b5 100644 --- a/src/test/java/com/github/f4b6a3/ulid/factory/MonotonicUlidFactoryTest.java +++ b/src/test/java/com/github/f4b6a3/ulid/factory/MonotonicFactoryTest.java @@ -12,7 +12,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Random; -public class MonotonicUlidFactoryTest extends UlidFactoryTest { +public class MonotonicFactoryTest extends UlidFactoryTest { @Test public void testGetUlid() { @@ -78,8 +78,7 @@ public class MonotonicUlidFactoryTest extends UlidFactoryTest { // Instantiate and start many threads for (int i = 0; i < THREAD_TOTAL; i++) { - Random random = new Random(); - UlidFactory factory = UlidCreator.getMonotonicFactory().withRandomGenerator(random::nextBytes); + UlidFactory factory = new MonotonicFactory(new Random()); threads[i] = new TestThread(factory, DEFAULT_LOOP_MAX); threads[i].start(); }