1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.common.guid;
21
22 import org.waarp.common.utility.Hexa;
23 import org.waarp.common.utility.StringUtils;
24
25 import java.util.Arrays;
26 import java.util.concurrent.atomic.AtomicInteger;
27
28
29
30
31
32
33
34
35
36
37
38
39 public final class LongUuid {
40
41
42
43 private static final int SIZE_COUNTER = 20;
44
45
46
47 private static final int MIN_COUNTER = 0;
48
49
50
51 private static final int MAX_COUNTER = (1 << SIZE_COUNTER) - 1;
52
53
54
55 private static final AtomicInteger COUNTER =
56 new AtomicInteger(Math.abs(StringUtils.RANDOM.nextInt(SIZE_COUNTER)));
57
58
59
60 private static final int UUIDSIZE = 8;
61
62
63
64
65
66 private final byte[] uuid = { 0, 0, 0, 0, 0, 0, 0, 0 };
67
68 static final synchronized int getCounter() {
69 if (COUNTER.compareAndSet(MAX_COUNTER, MIN_COUNTER)) {
70 return MAX_COUNTER;
71 } else {
72 return COUNTER.getAndIncrement();
73 }
74 }
75
76 public static final long getLongUuid() {
77 final long time = System.currentTimeMillis();
78
79 final int count = getCounter();
80
81
82
83 long uuidAsLong = (JvmProcessId.jvmId & 0xF0L) << 56;
84 uuidAsLong |= (time & 0xFFFFFFFFFFL) << 20;
85 uuidAsLong |= count & 0xFFFFFL;
86 return uuidAsLong;
87 }
88
89
90
91
92
93 public LongUuid() {
94 this(getLongUuid());
95 }
96
97
98
99
100
101
102 public LongUuid(final byte[] bytes) {
103 if (bytes.length != UUIDSIZE) {
104 throw new RuntimeException(
105 "Attempted to parse malformed UUID: " + Arrays.toString(bytes));
106 }
107 System.arraycopy(bytes, 0, uuid, 0, UUIDSIZE);
108 }
109
110 public LongUuid(final long value) {
111 uuid[0] = (byte) (value >> 56);
112 uuid[1] = (byte) (value >> 48);
113 uuid[2] = (byte) (value >> 40);
114 uuid[3] = (byte) (value >> 32);
115 uuid[4] = (byte) (value >> 24);
116 uuid[5] = (byte) (value >> 16);
117 uuid[6] = (byte) (value >> 8);
118 uuid[7] = (byte) value;
119 }
120
121 public LongUuid(final String idsource) {
122 final String id = idsource.trim();
123
124 if (id.length() != UUIDSIZE * 2) {
125 throw new RuntimeException("Attempted to parse malformed UUID: " + id);
126 }
127 System.arraycopy(Hexa.fromHex(id), 0, uuid, 0, UUIDSIZE);
128 }
129
130 @Override
131 public String toString() {
132 return Hexa.toHex(uuid);
133 }
134
135
136
137
138
139
140 public final byte[] getBytes() {
141 return Arrays.copyOf(uuid, UUIDSIZE);
142 }
143
144
145
146
147
148
149 public final int getProcessId() {
150 return (uuid[0] >> 4 & 0x0F);
151 }
152
153
154
155
156
157
158 public final long getTimestamp() {
159 long time;
160 time = ((long) uuid[0] & 0x0F) << 36;
161 time |= ((long) uuid[1] & 0xFF) << 28;
162 time |= ((long) uuid[2] & 0xFF) << 20;
163 time |= ((long) uuid[3] & 0xFF) << 12;
164 time |= ((long) uuid[4] & 0xFF) << 4;
165 time |= ((long) uuid[5] & 0xF0) >> 4;
166 return time;
167 }
168
169 @Override
170 public final boolean equals(final Object o) {
171 if (!(o instanceof LongUuid)) {
172 return false;
173 }
174 return this == o || Arrays.equals(uuid, ((LongUuid) o).uuid);
175 }
176
177 @Override
178 public final int hashCode() {
179 return Arrays.hashCode(uuid);
180 }
181
182
183
184
185 public final long getLong() {
186 long value = ((long) uuid[0] & 0xFF) << 56;
187 value |= ((long) uuid[1] & 0xFF) << 48;
188 value |= ((long) uuid[2] & 0xFF) << 40;
189 value |= ((long) uuid[3] & 0xFF) << 32;
190 value |= ((long) uuid[4] & 0xFF) << 24;
191 value |= ((long) uuid[5] & 0xFF) << 16;
192 value |= ((long) uuid[6] & 0xFF) << 8;
193 value |= (long) uuid[7] & 0xFF;
194 return value;
195 }
196 }