]> git.argeo.org Git - lgpl/argeo-commons.git/blob - UuidFactory.java
dc83f48ec10ea62fbb5ea4c08578a27ae6276d43
[lgpl/argeo-commons.git] / UuidFactory.java
1 package org.argeo.api.uuid;
2
3 import static java.nio.charset.StandardCharsets.UTF_8;
4
5 import java.nio.charset.Charset;
6 import java.util.Objects;
7 import java.util.UUID;
8 import java.util.concurrent.ThreadLocalRandom;
9 import java.util.function.Supplier;
10
11 /**
12 * A provider of RFC 4122 {@link UUID}s. Only the RFC 4122 variant (also known
13 * as Leach–Salz variant) is supported. The default, returned by the
14 * {@link Supplier#get()} method MUST be a v4 UUID (random).
15 *
16 * @see UUID
17 * @see https://datatracker.ietf.org/doc/html/rfc4122
18 */
19 public interface UuidFactory extends Supplier<UUID> {
20 /*
21 * DEFAULT
22 */
23 /**
24 * The default {@link UUID} to provide, either random (v4) or time based (v1).
25 * It SHOULD wrap either {@link #timeUUID()} (recommended) or
26 * {@link #randomUUID()}.
27 */
28 @Override
29 UUID get();
30
31 /*
32 * TIME-BASED (version 1)
33 */
34 /**
35 * A new time based {@link UUID} (v1) with efforts to make it unique on this
36 * node.
37 */
38 UUID timeUUID();
39
40 /*
41 * NAME BASED (version 3 and 5)
42 */
43 /**
44 * A new {@link UUID} v5, which an SHA1 digest of namespace and the provided
45 * bytes. This use to build names and implementation MAY restrict the maximal
46 * size of the byte array.
47 *
48 * @see UuidFactory#NAMESPACE_UUID_DNS
49 * @see UuidFactory#NAMESPACE_UUID_URL
50 * @see UuidFactory#NAMESPACE_UUID_OID
51 * @see UuidFactory#NAMESPACE_UUID_X500
52 */
53 UUID nameUUIDv5(UUID namespace, byte[] data);
54
55 /**
56 * A new {@link UUID} v3, which a MD5 digest of namespace and the provided
57 * bytes. This use to build names and implementation MAY restrict the maximal
58 * size of the byte array.
59 *
60 * @see UuidFactory#NAMESPACE_UUID_DNS
61 * @see UuidFactory#NAMESPACE_UUID_URL
62 * @see UuidFactory#NAMESPACE_UUID_OID
63 * @see UuidFactory#NAMESPACE_UUID_X500
64 */
65 UUID nameUUIDv3(UUID namespace, byte[] data);
66
67 /**
68 * A convenience method to generate a name based UUID v5 based on a string,
69 * using the UTF-8 charset.
70 *
71 * @see UuidFactory#nameUUIDv5(UUID, byte[])
72 */
73 default UUID nameUUIDv5(UUID namespace, String name) {
74 return nameUUIDv5(namespace, name, UTF_8);
75 }
76
77 /**
78 * A convenience method to generate a name based UUID v5 based on a string.
79 *
80 * @see UuidFactory#nameUUIDv5(UUID, byte[])
81 */
82 default UUID nameUUIDv5(UUID namespace, String name, Charset charset) {
83 Objects.requireNonNull(name, "Name cannot be null");
84 return nameUUIDv5(namespace, name.getBytes(charset));
85 }
86
87 /**
88 * A convenience method to generate a name based UUID v3 based on a string,
89 * using the UTF-8 charset.
90 *
91 * @see UuidFactory#nameUUIDv3(UUID, byte[])
92 */
93 default UUID nameUUIDv3(UUID namespace, String name) {
94 return nameUUIDv3(namespace, name, UTF_8);
95 }
96
97 /**
98 * A convenience method to generate a name based UUID v3 based on a string.
99 *
100 * @see UuidFactory#nameUUIDv3(UUID, byte[])
101 */
102 default UUID nameUUIDv3(UUID namespace, String name, Charset charset) {
103 Objects.requireNonNull(name, "Name cannot be null");
104 return nameUUIDv3(namespace, name.getBytes(charset));
105 }
106
107 /*
108 * RANDOM (version 4)
109 */
110 /**
111 * A random UUID at least as good as {@link UUID#randomUUID()}, but with efforts
112 * to make it even more random, using more secure algorithms and resseeding.
113 */
114 UUID randomUUIDStrong();
115
116 /**
117 * An {@link UUID} generated based on {@link ThreadLocalRandom}. Implementations
118 * should always provide it synchronously.
119 */
120 UUID randomUUIDWeak();
121
122 /**
123 * The default random {@link UUID} (v4) generator to use. This default
124 * implementation returns {@link #randomUUIDStrong()}. In general, one should
125 * use {@link UUID#randomUUID()} to generate random UUID, as it is certainly the
126 * best balanced and to avoid unnecessary dependencies with an API. The
127 * implementations provided here are either when is looking for something
128 * "stronger" ({@link #randomUUIDStrong()} or faster {@link #randomUUIDWeak()}.
129 */
130 default UUID randomUUID() {
131 return randomUUIDStrong();
132 }
133
134 /*
135 * STANDARD UUIDs
136 */
137
138 /** Nil UUID (00000000-0000-0000-0000-000000000000). */
139 final static UUID NIL_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000");
140 /**
141 * Standard DNS namespace ID for type 3 or 5 UUID (as defined in Appendix C of
142 * RFC4122).
143 */
144 final static UUID NAMESPACE_UUID_DNS = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
145 /**
146 * Standard URL namespace ID for type 3 or 5 UUID (as defined in Appendix C of
147 * RFC4122).
148 */
149 final static UUID NAMESPACE_UUID_URL = UUID.fromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8");
150 /**
151 * Standard OID namespace ID (typically an LDAP type) for type 3 or 5 UUID (as
152 * defined in Appendix C of RFC4122).
153 */
154 final static UUID NAMESPACE_UUID_OID = UUID.fromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8");
155 /**
156 * Standard X500 namespace ID (typically an LDAP DN) for type 3 or 5 UUID (as
157 * defined in Appendix C of RFC4122).
158 */
159 final static UUID NAMESPACE_UUID_X500 = UUID.fromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8");
160
161 /*
162 * UTILITIES
163 */
164 /** Whether this {@link UUID} is random (v4). */
165 static boolean isRandom(UUID uuid) {
166 return uuid.version() == 4;
167 }
168
169 /** Whether this {@link UUID} is time based (v1). */
170 static boolean isTimeBased(UUID uuid) {
171 return uuid.version() == 1;
172 }
173
174 /**
175 * Whether this UUID is time based but was not generated from an IEEE 802
176 * address, as per Section 4.5 of RFC4122.
177 *
178 * @see https://datatracker.ietf.org/doc/html/rfc4122#section-4.5
179 */
180 static boolean isTimeBasedWithMacAddress(UUID uuid) {
181 if (uuid.version() == 1) {
182 return (uuid.node() & 1L) == 0;
183 } else
184 return false;
185 }
186
187 /** Whether this {@link UUID} is name based (v3 or v5). */
188 static boolean isNameBased(UUID uuid) {
189 return uuid.version() == 3 || uuid.version() == 5;
190 }
191 }