+// @Deprecated
+// public static UUID timeBasedUUID() {
+// return timeBasedUUID(LocalDateTime.now(ZoneOffset.UTC));
+// }
+//
+// @Deprecated
+// public static UUID timeBasedRandomUUID() {
+// return timeBasedRandomUUID(LocalDateTime.now(ZoneOffset.UTC), RANDOM);
+// }
+//
+// @Deprecated
+// public static UUID timeBasedUUID(LocalDateTime time) {
+// if (HARDWARE_ADDRESS == null)
+// return timeBasedRandomUUID(time, RANDOM);
+// return timeBasedUUID(time, BitSet.valueOf(HARDWARE_ADDRESS));
+// }
+//
+// @Deprecated
+// public static UUID timeBasedAddressUUID(LocalDateTime time, NetworkInterface nic) throws SocketException {
+// byte[] nodeBytes = nic.getHardwareAddress();
+// BitSet node = BitSet.valueOf(nodeBytes);
+// return timeBasedUUID(time, node);
+// }
+//
+// @Deprecated
+// public static UUID timeBasedRandomUUID(LocalDateTime time, Random random) {
+// byte[] nodeBytes = new byte[6];
+// random.nextBytes(nodeBytes);
+// BitSet node = BitSet.valueOf(nodeBytes);
+// // set random marker
+// node.set(0, true);
+// return timeBasedUUID(time, node);
+// }
+//
+// @Deprecated
+// public static UUID timeBasedUUID(LocalDateTime time, BitSet node) {
+// // most significant
+// Duration duration = Duration.between(GREGORIAN_START, time);
+//
+// // Number of 100 ns intervals in one second: 1000000000 / 100 = 10000000
+// long timeNanos = duration.getSeconds() * 10000000 + duration.getNano() / 100;
+// BitSet timeBits = BitSet.valueOf(new long[] { timeNanos });
+// assert timeBits.length() <= 60;
+//
+// int clockSequence;
+// synchronized (CLOCK_SEQUENCE) {
+// clockSequence = CLOCK_SEQUENCE.incrementAndGet();
+// if (clockSequence > 16384)
+// CLOCK_SEQUENCE.set(0);
+// }
+// BitSet clockSequenceBits = BitSet.valueOf(new long[] { clockSequence });
+//
+// // Build the UUID, bit by bit
+// // see https://tools.ietf.org/html/rfc4122#section-4.2.2
+// // time
+// BitSet time_low = new BitSet(32);
+// BitSet time_mid = new BitSet(16);
+// BitSet time_hi_and_version = new BitSet(16);
+//
+// for (int i = 0; i < 60; i++) {
+// if (i < 32)
+// time_low.set(i, timeBits.get(i));
+// else if (i < 48)
+// time_mid.set(i - 32, timeBits.get(i));
+// else
+// time_hi_and_version.set(i - 48, timeBits.get(i));
+// }
+// // version
+// time_hi_and_version.set(12, true);
+// time_hi_and_version.set(13, false);
+// time_hi_and_version.set(14, false);
+// time_hi_and_version.set(15, false);
+//
+// // clock sequence
+// BitSet clk_seq_hi_res = new BitSet(8);
+// BitSet clk_seq_low = new BitSet(8);
+// for (int i = 0; i < 8; i++) {
+// clk_seq_low.set(i, clockSequenceBits.get(i));
+// }
+// for (int i = 8; i < 14; i++) {
+// clk_seq_hi_res.set(i - 8, clockSequenceBits.get(i));
+// }
+// // variant
+// clk_seq_hi_res.set(6, false);
+// clk_seq_hi_res.set(7, true);
+//
+//// String str = toHexString(time_low.toLongArray()[0]) + "-" + toHexString(time_mid.toLongArray()[0]) + "-"
+//// + toHexString(time_hi_and_version.toLongArray()[0]) + "-"
+//// + toHexString(clock_seq_hi_and_reserved.toLongArray()[0]) + toHexString(clock_seq_low.toLongArray()[0])
+//// + "-" + toHexString(node.toLongArray()[0]);
+//// UUID uuid = UUID.fromString(str);
+//
+// BitSet uuidBits = new BitSet(128);
+// for (int i = 0; i < 128; i++) {
+// if (i < 48)
+// uuidBits.set(i, node.get(i));
+// else if (i < 56)
+// uuidBits.set(i, clk_seq_low.get(i - 48));
+// else if (i < 64)
+// uuidBits.set(i, clk_seq_hi_res.get(i - 56));
+// else if (i < 80)
+// uuidBits.set(i, time_hi_and_version.get(i - 64));
+// else if (i < 96)
+// uuidBits.set(i, time_mid.get(i - 80));
+// else
+// uuidBits.set(i, time_low.get(i - 96));
+// }
+//
+// long[] uuidLongs = uuidBits.toLongArray();
+// assert uuidLongs.length == 2;
+// UUID uuid = new UUID(uuidLongs[1], uuidLongs[0]);
+//
+// // tests
+// assert uuid.node() == node.toLongArray()[0];
+// assert uuid.timestamp() == timeNanos;
+// assert uuid.clockSequence() == clockSequence;
+// assert uuid.version() == 1;
+// assert uuid.variant() == 2;
+// return uuid;
+// }
+
+ /*
+ * NAME BASED (version 3 and 5)
+ */
+
+ public static UUID nameUUIDv5(UUID namespace, String name) {
+ Objects.requireNonNull(namespace, "Namespace cannot be null");
+ Objects.requireNonNull(name, "Name cannot be null");
+ return nameUUIDv5(namespace, name.getBytes(StandardCharsets.UTF_8));
+ }
+
+ public static UUID nameUUIDv5(UUID namespace, byte[] name) {
+ byte[] bytes = DigestUtils.sha1(toBytes(namespace), name);
+ bytes[6] &= 0x0f;
+ bytes[6] |= 0x50;// v5
+ bytes[8] &= 0x3f;
+ bytes[8] |= 0x80;// variant 1
+ UUID result = fromBytes(bytes, 0);
+ return result;
+ }
+
+ public static UUID nameUUIDv3(UUID namespace, String name) {
+ Objects.requireNonNull(namespace, "Namespace cannot be null");
+ Objects.requireNonNull(name, "Name cannot be null");
+ return nameUUIDv3(namespace, name.getBytes(StandardCharsets.UTF_8));
+ }
+
+ public static UUID nameUUIDv3(UUID namespace, byte[] name) {
+ byte[] arr = new byte[name.length + 16];
+ copyBytes(namespace, arr, 0);
+ System.arraycopy(name, 0, arr, 16, name.length);
+ return UUID.nameUUIDFromBytes(arr);
+ }
+
+ /*
+ * RANDOM v4
+ */
+ public static UUID unsecureRandomUUID() {
+ byte[] arr = new byte[16];
+ UNSECURE_RANDOM.nextBytes(arr);
+ arr[6] &= 0x0f;
+ arr[6] |= 0x40;// v4
+ arr[8] &= 0x3f;
+ arr[8] |= 0x80;// variant 1
+ return fromBytes(arr);
+ }
+
+ /*
+ * UTILITIES
+ */
+ /**
+ * Convert bytes to an UUID. Byte array must not be null and be exactly of
+ * length 16.
+ */
+ public static UUID fromBytes(byte[] data) {
+ Objects.requireNonNull(data, "Byte array must not be null");
+ if (data.length != 16)
+ throw new IllegalArgumentException("Byte array as length " + data.length);
+ return fromBytes(data, 0);
+ }
+
+ /**
+ * Convert bytes to an UUID, starting to read the array at this offset.
+ */
+ public static UUID fromBytes(byte[] data, int offset) {
+ Objects.requireNonNull(data, "Byte array cannot be null");
+ long msb = 0;
+ long lsb = 0;
+ for (int i = offset; i < 8 + offset; i++)
+ msb = (msb << 8) | (data[i] & 0xff);
+ for (int i = 8 + offset; i < 16 + offset; i++)
+ lsb = (lsb << 8) | (data[i] & 0xff);
+ return new UUID(msb, lsb);
+ }
+
+ public static byte[] toBytes(UUID uuid) {
+ Objects.requireNonNull(uuid, "UUID cannot be null");
+ long msb = uuid.getMostSignificantBits();
+ long lsb = uuid.getLeastSignificantBits();
+ return BytesUtils.toBytes(msb, lsb);
+ }
+
+ public static void copyBytes(UUID uuid, byte[] arr, int offset) {
+ Objects.requireNonNull(uuid, "UUID cannot be null");
+ long msb = uuid.getMostSignificantBits();
+ long lsb = uuid.getLeastSignificantBits();
+ BytesUtils.copyBytes(msb, lsb, arr, offset);
+ }
+
+ /**
+ * Converts an UUID to a binary string (list of 0 and 1), with a separator to
+ * make it more readable.
+ */