Integrate UUID API
[lgpl/argeo-commons.git] / org.argeo.api.uuid / src / org / argeo / api / uuid / UuidFactory.java
diff --git a/org.argeo.api.uuid/src/org/argeo/api/uuid/UuidFactory.java b/org.argeo.api.uuid/src/org/argeo/api/uuid/UuidFactory.java
new file mode 100644 (file)
index 0000000..a297061
--- /dev/null
@@ -0,0 +1,129 @@
+package org.argeo.api.uuid;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import java.util.Objects;
+import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.function.Supplier;
+
+/**
+ * A provider of RFC 4122 {@link UUID}s. Only the RFC 4122 variant (also known
+ * as Leach–Salz variant) is supported. The default, returned by the
+ * {@link Supplier#get()} method MUST be a v4 UUID (random).
+ * 
+ * @see UUID
+ * @see https://datatracker.ietf.org/doc/html/rfc4122
+ */
+public interface UuidFactory extends Supplier<UUID> {
+       /*
+        * TIME-BASED (version 1)
+        */
+
+       UUID timeUUID();
+
+       UUID timeUUIDwithMacAddress();
+
+       /*
+        * NAME BASED (version 3 and 5)
+        */
+
+       UUID nameUUIDv5(UUID namespace, byte[] data);
+
+       UUID nameUUIDv3(UUID namespace, byte[] data);
+
+       default UUID nameUUIDv5(UUID namespace, String name) {
+               Objects.requireNonNull(name, "Name cannot be null");
+               return nameUUIDv5(namespace, name.getBytes(UTF_8));
+       }
+
+       default UUID nameUUIDv3(UUID namespace, String name) {
+               Objects.requireNonNull(name, "Name cannot be null");
+               return nameUUIDv3(namespace, name.getBytes(UTF_8));
+       }
+
+       /*
+        * RANDOM (version 4)
+        */
+       /** A random UUID at least as good as {@link UUID#randomUUID()}. */
+       UUID randomUUIDStrong();
+
+       /**
+        * An {@link UUID} generated based on {@link ThreadLocalRandom}. Implementations
+        * should always provide it synchronously.
+        */
+       UUID randomUUIDWeak();
+
+       /**
+        * The default random {@link UUID} (v4) generator to use. This default
+        * implementation returns {@link #randomUUIDStrong()}.
+        */
+       default UUID randomUUID() {
+               return randomUUIDStrong();
+       }
+
+       /**
+        * The default {@link UUID} to provide, either random (v4) or time based (v1).
+        * This default implementations returns {@link #randomUUID()}.
+        */
+       @Override
+       default UUID get() {
+               return randomUUID();
+       }
+
+       /*
+        * STANDARD UUIDs
+        */
+
+       /** Nil UUID (00000000-0000-0000-0000-000000000000). */
+       final static UUID NIL_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000");
+       /**
+        * Standard DNS namespace ID for type 3 or 5 UUID (as defined in Appendix C of
+        * RFC4122).
+        */
+       final static UUID NS_DNS = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
+       /**
+        * Standard URL namespace ID for type 3 or 5 UUID (as defined in Appendix C of
+        * RFC4122).
+        */
+       final static UUID NS_URL = UUID.fromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8");
+       /**
+        * Standard OID namespace ID (typically an LDAP type) for type 3 or 5 UUID (as
+        * defined in Appendix C of RFC4122).
+        */
+       final static UUID NS_OID = UUID.fromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8");
+       /**
+        * Standard X500 namespace ID (typically an LDAP DN) for type 3 or 5 UUID (as
+        * defined in Appendix C of RFC4122).
+        */
+       final static UUID NS_X500 = UUID.fromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8");
+
+       /*
+        * UTILITIES
+        */
+
+       static boolean isRandom(UUID uuid) {
+               return uuid.version() == 4;
+       }
+
+       static boolean isTimeBased(UUID uuid) {
+               return uuid.version() == 1;
+       }
+
+       /**
+        * Whether this UUID is time based but was not generated from an IEEE 802
+        * address, as per Section 4.5 of RFC4122.
+        * 
+        * @see https://datatracker.ietf.org/doc/html/rfc4122#section-4.5
+        */
+       static boolean isTimeBasedWithMacAddress(UUID uuid) {
+               if (uuid.version() == 1) {
+                       return (uuid.node() & 1L) == 0;
+               } else
+                       return false;
+       }
+
+       static boolean isNameBased(UUID uuid) {
+               return uuid.version() == 3 || uuid.version() == 5;
+       }
+}