Add Hash ULID generator methods. #25
This commit is contained in:
parent
41c15148d3
commit
644ba86e2c
|
@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
Add Hash ULID generator methods. #25
|
||||||
Add a MIN and MAX constants and methods. #26
|
Add a MIN and MAX constants and methods. #26
|
||||||
|
|
||||||
## [5.2.0] - 2023-??-??
|
## [5.2.0] - 2023-??-??
|
||||||
|
|
|
@ -43,7 +43,7 @@ Add these lines to your `pom.xml`.
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.f4b6a3</groupId>
|
<groupId>com.github.f4b6a3</groupId>
|
||||||
<artifactId>ulid-creator</artifactId>
|
<artifactId>ulid-creator</artifactId>
|
||||||
<version>5.1.0</version>
|
<version>5.2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
See more options in [maven.org](https://search.maven.org/artifact/com.github.f4b6a3/ulid-creator).
|
See more options in [maven.org](https://search.maven.org/artifact/com.github.f4b6a3/ulid-creator).
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* MIT License
|
* MIT License
|
||||||
*
|
*
|
||||||
* Copyright (c) 2020-2022 Fabio Lima
|
* Copyright (c) 2020-2023 Fabio Lima
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -24,11 +24,19 @@
|
||||||
|
|
||||||
package com.github.f4b6a3.ulid;
|
package com.github.f4b6a3.ulid;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that generates ULIDs.
|
* A class that generates ULIDs.
|
||||||
* <p>
|
* <p>
|
||||||
* Both types of ULID can be easily created by this generator, i.e. monotonic
|
* Both types of ULID can be easily created by this generator, i.e. monotonic
|
||||||
* and non-monotonic.
|
* and non-monotonic.
|
||||||
|
* <p>
|
||||||
|
* In addition, a "non-standard" hash-based ULID can also be generated, in which
|
||||||
|
* the random component is replaced with the first 10 bytes of an SHA-256 hash.
|
||||||
*/
|
*/
|
||||||
public final class UlidCreator {
|
public final class UlidCreator {
|
||||||
|
|
||||||
|
@ -37,6 +45,8 @@ public final class UlidCreator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a ULID.
|
* Returns a ULID.
|
||||||
|
* <p>
|
||||||
|
* The random component is reset for each new ULID generated.
|
||||||
*
|
*
|
||||||
* @return a ULID
|
* @return a ULID
|
||||||
*/
|
*/
|
||||||
|
@ -45,7 +55,9 @@ public final class UlidCreator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a ULID with a given time.
|
* Returns a ULID.
|
||||||
|
* <p>
|
||||||
|
* The random component is reset for each new ULID generated.
|
||||||
*
|
*
|
||||||
* @param time a number of milliseconds since 1970-01-01 (Unix epoch).
|
* @param time a number of milliseconds since 1970-01-01 (Unix epoch).
|
||||||
* @return a ULID
|
* @return a ULID
|
||||||
|
@ -56,6 +68,9 @@ public final class UlidCreator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Monotonic ULID.
|
* Returns a Monotonic ULID.
|
||||||
|
* <p>
|
||||||
|
* The random component is incremented for each new ULID generated in the same
|
||||||
|
* millisecond.
|
||||||
*
|
*
|
||||||
* @return a ULID
|
* @return a ULID
|
||||||
*/
|
*/
|
||||||
|
@ -64,7 +79,10 @@ public final class UlidCreator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Monotonic ULID with a given time.
|
* Returns a Monotonic ULID.
|
||||||
|
* <p>
|
||||||
|
* The random component is incremented for each new ULID generated in the same
|
||||||
|
* millisecond.
|
||||||
*
|
*
|
||||||
* @param time a number of milliseconds since 1970-01-01 (Unix epoch).
|
* @param time a number of milliseconds since 1970-01-01 (Unix epoch).
|
||||||
* @return a ULID
|
* @return a ULID
|
||||||
|
@ -73,6 +91,68 @@ public final class UlidCreator {
|
||||||
return MonotonicFactoryHolder.INSTANCE.create(time);
|
return MonotonicFactoryHolder.INSTANCE.create(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Hash ULID.
|
||||||
|
* <p>
|
||||||
|
* The random component is replaced with the first 10 bytes of an SHA-256 hash.
|
||||||
|
* <p>
|
||||||
|
* It always returns the same ULID for a specific pair of {@code time} and
|
||||||
|
* {@code string}.
|
||||||
|
* <p>
|
||||||
|
* Usage example:
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* long time = file.getCreatedAt();
|
||||||
|
* String name = file.getFileName();
|
||||||
|
* Ulid ulid = HashUlid.generate(time, name);
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* @param time a number of milliseconds since 1970-01-01 (Unix epoch).
|
||||||
|
* @param string a string to be hashed using SHA-256 algorithm.
|
||||||
|
* @return a ULID
|
||||||
|
* @since 5.2.0
|
||||||
|
*/
|
||||||
|
public static Ulid getHashUlid(final long time, String string) {
|
||||||
|
byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
|
||||||
|
return getHashUlid(time, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Hash ULID.
|
||||||
|
* <p>
|
||||||
|
* The random component is replaced with the first 10 bytes of an SHA-256 hash.
|
||||||
|
* <p>
|
||||||
|
* It always returns the same ULID for a specific pair of {@code time} and
|
||||||
|
* {@code bytes}.
|
||||||
|
* <p>
|
||||||
|
* Usage example:
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* long time = file.getCreatedAt();
|
||||||
|
* byte[] bytes = file.getFileBinary();
|
||||||
|
* Ulid ulid = HashUlid.generate(time, bytes);
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* @param time a number of milliseconds since 1970-01-01 (Unix epoch).
|
||||||
|
* @param bytes a byte array to be hashed using SHA-256 algorithm.
|
||||||
|
* @return a ULID
|
||||||
|
* @since 5.2.0
|
||||||
|
*/
|
||||||
|
public static Ulid getHashUlid(final long time, byte[] bytes) {
|
||||||
|
// Calculate the hash and take the first 10 bytes
|
||||||
|
byte[] hash = hasher("SHA-256").digest(bytes);
|
||||||
|
byte[] rand = Arrays.copyOf(hash, 10);
|
||||||
|
return new Ulid(time, rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MessageDigest hasher(final String algorithm) {
|
||||||
|
try {
|
||||||
|
return MessageDigest.getInstance(algorithm);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(String.format("%s not supported", algorithm));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class UlidFactoryHolder {
|
private static class UlidFactoryHolder {
|
||||||
static final UlidFactory INSTANCE = UlidFactory.newInstance();
|
static final UlidFactory INSTANCE = UlidFactory.newInstance();
|
||||||
}
|
}
|
||||||
|
|
|
@ -629,6 +629,32 @@ public class UlidTest extends UlidFactoryTest {
|
||||||
checkCreationTime(list, startTime, endTime);
|
checkCreationTime(list, startTime, endTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetHashUlid() throws NoSuchAlgorithmException {
|
||||||
|
|
||||||
|
Ulid prev = Ulid.MIN;
|
||||||
|
for (int i = 0; i < DEFAULT_LOOP_MAX; i++) {
|
||||||
|
|
||||||
|
long time = (new Random()).nextLong() >>> 16;
|
||||||
|
String string = UUID.randomUUID().toString();
|
||||||
|
Ulid ulid = UlidCreator.getHashUlid(time, string);
|
||||||
|
|
||||||
|
assertNotNull(ulid);
|
||||||
|
assertNotEquals(prev, ulid);
|
||||||
|
assertNotEquals(Ulid.MIN, ulid);
|
||||||
|
assertNotEquals(Ulid.MAX, ulid);
|
||||||
|
assertEquals(time, ulid.getTime());
|
||||||
|
assertEquals(Arrays.toString(ulid.getRandom()), Arrays.toString(ulid.getRandom()));
|
||||||
|
|
||||||
|
MessageDigest md = MessageDigest.getInstance("SHA-256");
|
||||||
|
byte[] utf8 = string.getBytes(StandardCharsets.UTF_8);
|
||||||
|
byte[] hash = Arrays.copyOf(md.digest(utf8), 10);
|
||||||
|
assertEquals(Arrays.toString(ulid.getRandom()), Arrays.toString(hash));
|
||||||
|
|
||||||
|
prev = ulid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Ulid fromString(String string) {
|
public static Ulid fromString(String string) {
|
||||||
|
|
||||||
long time = 0;
|
long time = 0;
|
||||||
|
|
Loading…
Reference in New Issue