Add constructors in UlidFactory for random generators #12

New constructors:

- public UlidFactory(Random random) { }
- public UlidFactory(RandomGenerator randomGenerator) { }
This commit is contained in:
Fabio Lima 2021-07-18 01:21:41 -03:00
parent 0e1fe3f162
commit 0f431d01b1
13 changed files with 121 additions and 117 deletions

View File

@ -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

View File

@ -35,7 +35,7 @@ Add these lines to your `pom.xml`.
<dependency>
<groupId>com.github.f4b6a3</groupId>
<artifactId>ulid-creator</artifactId>
<version>3.1.1</version>
<version>3.2.0</version>
</dependency>
```
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

View File

@ -365,7 +365,8 @@ public final class Ulid implements Serializable, Comparable<Ulid> {
* 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<Ulid> {
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<Ulid> {
/**
* 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
*/

View File

@ -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();
}
}

View File

@ -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.

View File

@ -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.
*

View File

@ -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 <T> the type parameter
* @param randomGenerator a random generator
* @return {@link UlidFactory}
*/
@SuppressWarnings("unchecked")
public synchronized <T extends UlidFactory> T withRandomGenerator(RandomGenerator randomGenerator) {
this.randomGenerator = randomGenerator;
return (T) this;
}
}

View File

@ -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);
}
}

View File

@ -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,
})

View File

@ -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");

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}