--- /dev/null
+package org.argeo.api.uuid;
+
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * Base class for objects which are explicitly typed, based on the various UUID
+ * versions. Such a derivation hierarchy still represents the {@link UUID}
+ * itself, not the objects, data or concept that it identifies. Just like
+ * {@link UUID}s, {@link TypedUuid} should be used as identifier, not as base
+ * class for complex objects. It should rather be seen as a framework to build
+ * richer IDs, which are strictly compliant with the UUID specifications.
+ */
+public abstract class TypedUuid extends UuidHolder {
+ private static final long serialVersionUID = APM.SERIAL;
+
+ /** Default constructor. */
+ public TypedUuid(UUID uuid) {
+ super(uuid);
+ }
+
+ /**
+ * Whether this {@link UUID} has no meaning in itself (RFC4122 v3, v4 and v5,
+ * and Microsoft GUID). Only RFC4122 v1 and v2 can be interpreted.
+ */
+ public boolean isOpaque() {
+ if (uuid.variant() == 2) {// RFC4122
+ return uuid.version() == 4 || uuid.version() == 5 || uuid.version() == 3;
+ } else if (uuid.variant() == 6) {// Microsoft
+ return true;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Constructs a {@link TypedUuid} of the most appropriate subtype, based on this
+ * {@link UUID}.
+ */
+ public static TypedUuid of(UUID uuid) {
+ Objects.requireNonNull(uuid, "UUID cannot be null");
+ if (uuid.variant() == 2) {// RFC 4122
+ switch (uuid.version()) {
+ case 1:
+ return new TimeUuid(uuid);
+ case 4:
+ return new RandomUuid(uuid);
+ case 3:
+ case 5:
+ return new UnkownNameUuid(uuid);
+ default:
+ throw new IllegalArgumentException("UUIDs with version " + uuid.version() + " are not supported.");
+ }
+ } else if (uuid.variant() == 6) {// Microsoft
+ throw new IllegalArgumentException("Microsoft UUIDs (aka. GUIDs) are not supported.");
+ } else {
+ throw new IllegalArgumentException("UUIDs with variant " + uuid.variant() + " are not supported.");
+ }
+ }
+}