package org.ovirt.engine.core.compat;
import java.io.Serializable;
import java.util.Objects;
import java.util.UUID;
public class Guid implements Serializable, Comparable<Guid> {
/**
* Needed for the serialization/deserialization mechanism.
*/
private static final long serialVersionUID = 27305745737022810L;
private static final byte[] CHANGE_BYTE_ORDER_INDICES = { 3, 2, 1, 0,
5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 };
private static final byte[] KEEP_BYTE_ORDER_INDICES = { 0, 1, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
public static final Guid SYSTEM = new Guid("AAA00000-0000-0000-0000-123456789AAA");
public static final Guid EVERYONE = new Guid("EEE00000-0000-0000-0000-123456789EEE");
public static final Guid Empty = new Guid("00000000-0000-0000-0000-000000000000");
private UUID uuid;
/**
* This constructor should never be used directly - use {@link #Empty} instead.
* It is left here only because GWT requires it.
*/
@Deprecated
private Guid() {
this(Empty.getUuid());
}
public Guid(UUID uuid) {
this.uuid = uuid;
}
public Guid(byte[] guid, boolean keepByteOrder) {
// Note that the indexes are computed modulo the length of the input
// array because this is how they used to be calculated in the past,
// and some components (the REST API, for example) build GUIDs from
// array of bytes created from arbitrary strings, for example, in the
// BackendCapabilitiesResource class a GUID is built from the version
// string with this code:
//
// public String generateId(Version v) {
// Guid guid = new Guid((v.getMajor()+"."+v.getMinor()).getBytes(),true);
// return guid.toString();
// }
//
// This may result in an array of bytes shorter than the 16 bytes
// needed to build a GUID, thus the modulo operation is required.
byte[] indexes = keepByteOrder? KEEP_BYTE_ORDER_INDICES: CHANGE_BYTE_ORDER_INDICES;
long msb = 0;
long lsb = 0;
int length = guid.length;
for (int i = 0; i <= 7; i++) {
msb = (msb << 8) | (guid[indexes[i] % length] & 0xff);
}
for (int i = 8; i <= 15; i++) {
lsb = (lsb << 8) | (guid[indexes[i] % length] & 0xff);
}
uuid = new UUID(msb, lsb);
}
public Guid(String candidate) {
if (candidate == null) {
throw new NullPointerException(
"candidate can not be null please use static method createGuidFromString");
}
if (candidate.isEmpty()) {
uuid = Empty.getUuid();
} else {
uuid = UUID.fromString(candidate);
}
}
public static Guid newGuid() {
return new Guid(UUID.randomUUID());
}
public static Guid createGuidFromString(String candidate) {
return createGuidFromStringWithDefault(candidate, null);
}
public static Guid createGuidFromStringDefaultEmpty(String candidate) {
return createGuidFromStringWithDefault(candidate, Guid.Empty);
}
private static Guid createGuidFromStringWithDefault(String candidate, Guid defaultValue) {
if (candidate == null) {
return defaultValue;
}
return new Guid(candidate);
}
public static boolean isNullOrEmpty(Guid id) {
return id == null || id.equals(Empty);
}
public UUID getUuid() {
return uuid;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Guid)) {
return false;
}
Guid other = (Guid) obj;
return Objects.equals(uuid, other.uuid);
}
@Override
public int hashCode() {
return Objects.hashCode(uuid);
}
@Override
public int compareTo(Guid other) {
return this.getUuid().compareTo(other.getUuid());
}
@Override
public String toString() {
return uuid.toString();
}
public byte[] toByteArray() {
byte[] data = new byte[16];
long msb = uuid.getMostSignificantBits();
for (int i = 7; i >= 0; i--) {
data[i] = (byte) (msb & 0xff);
msb >>= 8;
}
long lsb = uuid.getLeastSignificantBits();
for (int i = 15; i >= 8; i--) {
data[i] = (byte) (lsb & 0xff);
lsb >>= 8;
}
return data;
}
}