]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.api.uuid/src/org/argeo/api/uuid/UuidFactory.java
Improve build and local deployment
[lgpl/argeo-commons.git] / org.argeo.api.uuid / src / org / argeo / api / uuid / 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 /*
22 * DEFAULT
23 */
24 /**
25 * The default {@link UUID} to provide, either random (v4) or time based (v1).
26 * It SHOULD wrap either {@link #timeUUID()} (recommended) or
27 * {@link #randomUUID()}.
28 */
29 @Override
30 UUID get();
31
32 /*
33 * TIME-BASED (version 1)
34 */
35 /**
36 * A new time based {@link UUID} (v1) with efforts to make it unique on this
37 * node.
38 */
39 UUID timeUUID();
40
41 /*
42 * NAME BASED (version 3 and 5)
43 */
44 /**
45 * A new {@link UUID} v5, which an SHA1 digest of namespace and the provided
46 * bytes. This use to build names and implementation MAY restrict the maximal
47 * size of the byte array.
48 *
49 * @see UuidFactory#NAMESPACE_UUID_DNS
50 * @see UuidFactory#NAMESPACE_UUID_URL
51 * @see UuidFactory#NAMESPACE_UUID_OID
52 * @see UuidFactory#NAMESPACE_UUID_X500
53 */
54 UUID nameUUIDv5(UUID namespace, byte[] data);
55
56 /**
57 * A new {@link UUID} v3, which a MD5 digest of namespace and the provided
58 * bytes. This use to build names and implementation MAY restrict the maximal
59 * size of the byte array.
60 *
61 * @see UuidFactory#NAMESPACE_UUID_DNS
62 * @see UuidFactory#NAMESPACE_UUID_URL
63 * @see UuidFactory#NAMESPACE_UUID_OID
64 * @see UuidFactory#NAMESPACE_UUID_X500
65 */
66 UUID nameUUIDv3(UUID namespace, byte[] data);
67
68 /**
69 * A convenience method to generate a name based UUID v5 based on a string,
70 * using the UTF-8 charset.
71 *
72 * @see UuidFactory#nameUUIDv5(UUID, byte[])
73 */
74 default UUID nameUUIDv5(UUID namespace, String name) {
75 return nameUUIDv5(namespace, name, UTF_8);
76 }
77
78 /**
79 * A convenience method to generate a name based UUID v5 based on a string.
80 *
81 * @see UuidFactory#nameUUIDv5(UUID, byte[])
82 */
83 default UUID nameUUIDv5(UUID namespace, String name, Charset charset) {
84 Objects.requireNonNull(name, "Name cannot be null");
85 return nameUUIDv5(namespace, name.getBytes(charset));
86 }
87
88 /**
89 * A convenience method to generate a name based UUID v3 based on a string,
90 * using the UTF-8 charset.
91 *
92 * @see UuidFactory#nameUUIDv3(UUID, byte[])
93 */
94 default UUID nameUUIDv3(UUID namespace, String name) {
95 return nameUUIDv3(namespace, name, UTF_8);
96 }
97
98 /**
99 * A convenience method to generate a name based UUID v3 based on a string.
100 *
101 * @see UuidFactory#nameUUIDv3(UUID, byte[])
102 */
103 default UUID nameUUIDv3(UUID namespace, String name, Charset charset) {
104 Objects.requireNonNull(name, "Name cannot be null");
105 return nameUUIDv3(namespace, name.getBytes(charset));
106 }
107
108 /*
109 * RANDOM (version 4)
110 */
111 /**
112 * A random UUID at least as good as {@link UUID#randomUUID()}, but with efforts
113 * to make it even more random, using more secure algorithms and resseeding.
114 */
115 UUID randomUUIDStrong();
116
117 /**
118 * An {@link UUID} generated based on {@link ThreadLocalRandom}. Implementations
119 * should always provide it synchronously.
120 */
121 UUID randomUUIDWeak();
122
123 /**
124 * The default random {@link UUID} (v4) generator to use. This default
125 * implementation returns {@link #randomUUIDStrong()}. In general, one should
126 * use {@link UUID#randomUUID()} to generate random UUID, as it is certainly the
127 * best balanced and to avoid unnecessary dependencies with an API. The
128 * implementations provided here are either when is looking for something
129 * "stronger" ({@link #randomUUIDStrong()} or faster {@link #randomUUIDWeak()}.
130 */
131 default UUID randomUUID() {
132 return randomUUIDStrong();
133 }
134
135 /*
136 * STANDARD UUIDs
137 */
138
139 /** Nil UUID (00000000-0000-0000-0000-000000000000). */
140 final static UUID NIL_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000");
141 /**
142 * Standard DNS namespace ID for type 3 or 5 UUID (as defined in Appendix C of
143 * RFC4122).
144 */
145 final static UUID NAMESPACE_UUID_DNS = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
146 /**
147 * Standard URL namespace ID for type 3 or 5 UUID (as defined in Appendix C of
148 * RFC4122).
149 */
150 final static UUID NAMESPACE_UUID_URL = UUID.fromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8");
151 /**
152 * Standard OID namespace ID (typically an LDAP type) for type 3 or 5 UUID (as
153 * defined in Appendix C of RFC4122).
154 */
155 final static UUID NAMESPACE_UUID_OID = UUID.fromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8");
156 /**
157 * Standard X500 namespace ID (typically an LDAP DN) for type 3 or 5 UUID (as
158 * defined in Appendix C of RFC4122).
159 */
160 final static UUID NAMESPACE_UUID_X500 = UUID.fromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8");
161
162 /*
163 * BIT LEVEL CONSTANTS
164 */
165 /** Base for the most significant bit of version 1 (time based) UUIDs. */
166 long MOST_SIG_VERSION1 = (1l << 12);
167 /** Base for the least significant part of RFC4122 (variant 2) UUIDs. */
168 long LEAST_SIG_RFC4122_VARIANT = (1l << 63);
169
170 /*
171 * UTILITIES
172 */
173 /** Whether this {@link UUID} is random (v4). */
174 static boolean isRandom(UUID uuid) {
175 return uuid.version() == 4;
176 }
177
178 /** Whether this {@link UUID} is time based (v1). */
179 static boolean isTimeBased(UUID uuid) {
180 return uuid.version() == 1;
181 }
182
183 /**
184 * Whether this UUID is time based but was not generated from an IEEE 802
185 * address, as per Section 4.5 of RFC4122.
186 *
187 * @see "https://datatracker.ietf.org/doc/html/rfc4122#section-4.5"
188 */
189 static boolean isTimeBasedWithMacAddress(UUID uuid) {
190 if (uuid.version() == 1) {
191 return (uuid.node() & 1L) == 0;
192 } else
193 return false;
194 }
195
196 /** Whether this {@link UUID} is name based (v3 or v5). */
197 static boolean isNameBased(UUID uuid) {
198 return uuid.version() == 3 || uuid.version() == 5;
199 }
200
201 /**
202 * The state of a time based UUID generator, as described and discussed in
203 * section 4.2.1 of RFC4122.
204 *
205 * @see "https://datatracker.ietf.org/doc/html/rfc4122#section-4.2.1"
206 */
207 interface TimeUuidState {
208 /** Current node id and clock sequence for this thread. */
209 long getLeastSignificantBits();
210
211 /** A new current timestamp for this thread. */
212 long getMostSignificantBits();
213
214 /**
215 * The last timestamp which was produced by this thread, as returned by
216 * {@link UUID#timestamp()}.
217 */
218 long getLastTimestamp();
219
220 /**
221 * The current clock sequence for this thread, as returned by
222 * {@link UUID#clockSequence()}.
223 */
224 long getClockSequence();
225 }
226 }