Document and clean up UUID factory API and implementation.
[lgpl/argeo-commons.git] / org.argeo.api.uuid / src / org / argeo / api / uuid / UuidFactory.java
index a2970618403f45002a2706ad9e48e0badf649c88..4ab6c2e4b754d7818be29a24fece361373b5f6e9 100644 (file)
@@ -2,6 +2,7 @@ package org.argeo.api.uuid;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import java.nio.charset.Charset;
 import java.util.Objects;
 import java.util.UUID;
 import java.util.concurrent.ThreadLocalRandom;
@@ -16,36 +17,101 @@ import java.util.function.Supplier;
  * @see https://datatracker.ietf.org/doc/html/rfc4122
  */
 public interface UuidFactory extends Supplier<UUID> {
+
        /*
-        * TIME-BASED (version 1)
+        * DEFAULT
         */
+       /**
+        * The default {@link UUID} to provide, either random (v4) or time based (v1).
+        * It SHOULD wrap either {@link #timeUUID()} (recommended) or
+        * {@link #randomUUID()}.
+        */
+       @Override
+       UUID get();
 
+       /*
+        * TIME-BASED (version 1)
+        */
+       /**
+        * A new time based {@link UUID} (v1) with efforts to make it unique on this
+        * node.
+        */
        UUID timeUUID();
 
-       UUID timeUUIDwithMacAddress();
-
        /*
         * NAME BASED (version 3 and 5)
         */
-
+       /**
+        * A new {@link UUID} v5, which an SHA1 digest of namespace and the provided
+        * bytes. This use to build names and implementation MAY restrict the maximal
+        * size of the byte array.
+        * 
+        * @see UuidFactory#NAMESPACE_UUID_DNS
+        * @see UuidFactory#NAMESPACE_UUID_URL
+        * @see UuidFactory#NAMESPACE_UUID_OID
+        * @see UuidFactory#NAMESPACE_UUID_X500
+        */
        UUID nameUUIDv5(UUID namespace, byte[] data);
 
+       /**
+        * A new {@link UUID} v3, which a MD5 digest of namespace and the provided
+        * bytes. This use to build names and implementation MAY restrict the maximal
+        * size of the byte array.
+        * 
+        * @see UuidFactory#NAMESPACE_UUID_DNS
+        * @see UuidFactory#NAMESPACE_UUID_URL
+        * @see UuidFactory#NAMESPACE_UUID_OID
+        * @see UuidFactory#NAMESPACE_UUID_X500
+        */
        UUID nameUUIDv3(UUID namespace, byte[] data);
 
+       /**
+        * A convenience method to generate a name based UUID v5 based on a string,
+        * using the UTF-8 charset.
+        * 
+        * @see UuidFactory#nameUUIDv5(UUID, byte[])
+        */
        default UUID nameUUIDv5(UUID namespace, String name) {
+               return nameUUIDv5(namespace, name, UTF_8);
+       }
+
+       /**
+        * A convenience method to generate a name based UUID v5 based on a string.
+        * 
+        * @see UuidFactory#nameUUIDv5(UUID, byte[])
+        */
+       default UUID nameUUIDv5(UUID namespace, String name, Charset charset) {
                Objects.requireNonNull(name, "Name cannot be null");
-               return nameUUIDv5(namespace, name.getBytes(UTF_8));
+               return nameUUIDv5(namespace, name.getBytes(charset));
        }
 
+       /**
+        * A convenience method to generate a name based UUID v3 based on a string,
+        * using the UTF-8 charset.
+        * 
+        * @see UuidFactory#nameUUIDv3(UUID, byte[])
+        */
        default UUID nameUUIDv3(UUID namespace, String name) {
+               return nameUUIDv3(namespace, name, UTF_8);
+       }
+
+       /**
+        * A convenience method to generate a name based UUID v3 based on a string.
+        * 
+        * @see UuidFactory#nameUUIDv3(UUID, byte[])
+        */
+       default UUID nameUUIDv3(UUID namespace, String name, Charset charset) {
                Objects.requireNonNull(name, "Name cannot be null");
-               return nameUUIDv3(namespace, name.getBytes(UTF_8));
+               return nameUUIDv3(namespace, name.getBytes(charset));
        }
 
        /*
         * RANDOM (version 4)
         */
-       /** A random UUID at least as good as {@link UUID#randomUUID()}. */
+       /**
+        * A random UUID at least as good as {@link UUID#randomUUID()}, but with efforts
+        * to make it even more random, using more secure algorithms and resseeding.
+        */
        UUID randomUUIDStrong();
 
        /**
@@ -56,21 +122,16 @@ public interface UuidFactory extends Supplier<UUID> {
 
        /**
         * The default random {@link UUID} (v4) generator to use. This default
-        * implementation returns {@link #randomUUIDStrong()}.
+        * implementation returns {@link #randomUUIDStrong()}. In general, one should
+        * use {@link UUID#randomUUID()} to generate random UUID, as it is certainly the
+        * best balanced and to avoid unnecessary dependencies with an API. The
+        * implementations provided here are either when is looking for something
+        * "stronger" ({@link #randomUUIDStrong()} or faster {@link #randomUUIDWeak()}.
         */
        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
         */
@@ -81,31 +142,40 @@ public interface UuidFactory extends Supplier<UUID> {
         * 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");
+       final static UUID NAMESPACE_UUID_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");
+       final static UUID NAMESPACE_UUID_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");
+       final static UUID NAMESPACE_UUID_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");
+       final static UUID NAMESPACE_UUID_X500 = UUID.fromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8");
 
        /*
-        * UTILITIES
+        * BIT LEVEL CONSTANTS
         */
+       /** Base for the most significant bit of version 1 (time based) UUIDs. */
+       long MOST_SIG_VERSION1 = (1l << 12);
+       /** Base for the least significant part of RFC4122 (variant 2) UUIDs. */
+       long LEAST_SIG_RFC4122_VARIANT = (1l << 63);
 
+       /*
+        * UTILITIES
+        */
+       /** Whether this {@link UUID} is random (v4). */
        static boolean isRandom(UUID uuid) {
                return uuid.version() == 4;
        }
 
+       /** Whether this {@link UUID} is time based (v1). */
        static boolean isTimeBased(UUID uuid) {
                return uuid.version() == 1;
        }
@@ -123,7 +193,34 @@ public interface UuidFactory extends Supplier<UUID> {
                        return false;
        }
 
+       /** Whether this {@link UUID} is name based (v3 or v5). */
        static boolean isNameBased(UUID uuid) {
                return uuid.version() == 3 || uuid.version() == 5;
        }
+
+       /**
+        * The state of a time based UUID generator, as described and discussed in
+        * section 4.2.1 of RFC4122.
+        * 
+        * @see https://datatracker.ietf.org/doc/html/rfc4122#section-4.2.1
+        */
+       interface TimeUuidState {
+               /** Current node id and clock sequence for this thread. */
+               long getLeastSignificantBits();
+
+               /** A new current timestamp for this thread. */
+               long getMostSignificantBits();
+
+               /**
+                * The last timestamp which was produced by this thread, as returned by
+                * {@link UUID#timestamp()}.
+                */
+               long getLastTimestamp();
+
+               /**
+                * The current clock sequence for this thread, as returned by
+                * {@link UUID#clockSequence()}.
+                */
+               long getClockSequence();
+       }
 }