1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.util;
45
46 import java.util.AbstractMap;
47 import java.util.AbstractSet;
48 import java.util.Iterator;
49 import java.util.Map;
50 import java.util.NoSuchElementException;
51 import java.util.Set;
52
53 import org.eclipse.jgit.lib.AnyObjectId;
54 import org.eclipse.jgit.lib.ObjectId;
55 import org.eclipse.jgit.lib.Ref;
56 import org.eclipse.jgit.lib.RefComparator;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 public class RefMap extends AbstractMap<String, Ref> {
77
78
79
80
81
82
83 final String prefix;
84
85
86 RefList<Ref> packed;
87
88
89
90
91
92
93
94
95
96 RefList<Ref> loose;
97
98
99
100
101
102
103
104
105
106 RefList<Ref> resolved;
107
108 int size;
109
110 boolean sizeIsValid;
111
112 private Set<Entry<String, Ref>> entrySet;
113
114
115
116
117 public RefMap() {
118 prefix = "";
119 packed = RefList.emptyList();
120 loose = RefList.emptyList();
121 resolved = RefList.emptyList();
122 }
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 @SuppressWarnings("unchecked")
144 public RefMap(String prefix, RefList<? extends Ref> packed,
145 RefList<? extends Ref> loose, RefList<? extends Ref> resolved) {
146 this.prefix = prefix;
147 this.packed = (RefList<Ref>) packed;
148 this.loose = (RefList<Ref>) loose;
149 this.resolved = (RefList<Ref>) resolved;
150 }
151
152
153 @Override
154 public boolean containsKey(Object name) {
155 return get(name) != null;
156 }
157
158
159 @Override
160 public Ref get(Object key) {
161 String name = toRefName((String) key);
162 Ref ref = resolved.get(name);
163 if (ref == null)
164 ref = loose.get(name);
165 if (ref == null)
166 ref = packed.get(name);
167 return ref;
168 }
169
170
171 @Override
172 public Ref./../org/eclipse/jgit/lib/Ref.html#Ref">Ref put(String keyName, Ref value) {
173 String name = toRefName(keyName);
174
175 if (!name.equals(value.getName()))
176 throw new IllegalArgumentException();
177
178 if (!resolved.isEmpty()) {
179
180
181 for (Ref ref : resolved)
182 loose = loose.put(ref);
183 resolved = RefList.emptyList();
184 }
185
186 int idx = loose.find(name);
187 if (0 <= idx) {
188 Ref prior = loose.get(name);
189 loose = loose.set(idx, value);
190 return prior;
191 } else {
192 Ref prior = get(keyName);
193 loose = loose.add(idx, value);
194 sizeIsValid = false;
195 return prior;
196 }
197 }
198
199
200 @Override
201 public Ref remove(Object key) {
202 String name = toRefName((String) key);
203 Ref res = null;
204 int idx;
205 if (0 <= (idx = packed.find(name))) {
206 res = packed.get(name);
207 packed = packed.remove(idx);
208 sizeIsValid = false;
209 }
210 if (0 <= (idx = loose.find(name))) {
211 res = loose.get(name);
212 loose = loose.remove(idx);
213 sizeIsValid = false;
214 }
215 if (0 <= (idx = resolved.find(name))) {
216 res = resolved.get(name);
217 resolved = resolved.remove(idx);
218 sizeIsValid = false;
219 }
220 return res;
221 }
222
223
224 @Override
225 public boolean isEmpty() {
226 return entrySet().isEmpty();
227 }
228
229
230 @Override
231 public Set<Entry<String, Ref>> entrySet() {
232 if (entrySet == null) {
233 entrySet = new AbstractSet<Entry<String, Ref>>() {
234 @Override
235 public Iterator<Entry<String, Ref>> iterator() {
236 return new SetIterator();
237 }
238
239 @Override
240 public int size() {
241 if (!sizeIsValid) {
242 size = 0;
243 Iterator<?> i = entrySet().iterator();
244 for (; i.hasNext(); i.next())
245 size++;
246 sizeIsValid = true;
247 }
248 return size;
249 }
250
251 @Override
252 public boolean isEmpty() {
253 if (sizeIsValid)
254 return 0 == size;
255 return !iterator().hasNext();
256 }
257
258 @Override
259 public void clear() {
260 packed = RefList.emptyList();
261 loose = RefList.emptyList();
262 resolved = RefList.emptyList();
263 size = 0;
264 sizeIsValid = true;
265 }
266 };
267 }
268 return entrySet;
269 }
270
271
272 @Override
273 public String toString() {
274 StringBuilder r = new StringBuilder();
275 boolean first = true;
276 r.append('[');
277 for (Ref ref : values()) {
278 if (first)
279 first = false;
280 else
281 r.append(", ");
282 r.append(ref);
283 }
284 r.append(']');
285 return r.toString();
286 }
287
288 private String toRefName(String name) {
289 if (0 < prefix.length())
290 name = prefix + name;
291 return name;
292 }
293
294 String toMapKey(Ref ref) {
295 String name = ref.getName();
296 if (0 < prefix.length())
297 name = name.substring(prefix.length());
298 return name;
299 }
300
301 private class SetIterator implements Iterator<Entry<String, Ref>> {
302 private int packedIdx;
303
304 private int looseIdx;
305
306 private int resolvedIdx;
307
308 private Entry<String, Ref> next;
309
310 SetIterator() {
311 if (0 < prefix.length()) {
312 packedIdx = -(packed.find(prefix) + 1);
313 looseIdx = -(loose.find(prefix) + 1);
314 resolvedIdx = -(resolved.find(prefix) + 1);
315 }
316 }
317
318 @Override
319 public boolean hasNext() {
320 if (next == null)
321 next = peek();
322 return next != null;
323 }
324
325 @Override
326 public Entry<String, Ref> next() {
327 if (hasNext()) {
328 Entry<String, Ref> r = next;
329 next = peek();
330 return r;
331 }
332 throw new NoSuchElementException();
333 }
334
335 public Entry<String, Ref> peek() {
336 if (packedIdx < packed.size() && looseIdx < loose.size()) {
337 Ref p = packed.get(packedIdx);
338 Ref l = loose.get(looseIdx);
339 int cmp = RefComparator.compareTo(p, l);
340 if (cmp < 0) {
341 packedIdx++;
342 return toEntry(p);
343 }
344
345 if (cmp == 0)
346 packedIdx++;
347 looseIdx++;
348 return toEntry(resolveLoose(l));
349 }
350
351 if (looseIdx < loose.size())
352 return toEntry(resolveLoose(loose.get(looseIdx++)));
353 if (packedIdx < packed.size())
354 return toEntry(packed.get(packedIdx++));
355 return null;
356 }
357
358 private Ref../../../../org/eclipse/jgit/lib/Ref.html#Ref">Ref resolveLoose(Ref l) {
359 if (resolvedIdx < resolved.size()) {
360 Ref r = resolved.get(resolvedIdx);
361 int cmp = RefComparator.compareTo(l, r);
362 if (cmp == 0) {
363 resolvedIdx++;
364 return r;
365 } else if (cmp > 0) {
366
367
368 throw new IllegalStateException();
369 }
370 }
371 return l;
372 }
373
374 private Ent toEntry(Ref p) {
375 if (p.getName().startsWith(prefix))
376 return new Ent(p);
377 packedIdx = packed.size();
378 looseIdx = loose.size();
379 resolvedIdx = resolved.size();
380 return null;
381 }
382
383 @Override
384 public void remove() {
385 throw new UnsupportedOperationException();
386 }
387 }
388
389 private class Ent implements Entry<String, Ref> {
390 private Ref ref;
391
392 Ent(Ref ref) {
393 this.ref = ref;
394 }
395
396 @Override
397 public String getKey() {
398 return toMapKey(ref);
399 }
400
401 @Override
402 public Ref getValue() {
403 return ref;
404 }
405
406 @Override
407 public Refef="../../../../org/eclipse/jgit/lib/Ref.html#Ref">Ref setValue(Ref value) {
408 Ref prior = put(getKey(), value);
409 ref = value;
410 return prior;
411 }
412
413 @Override
414 public int hashCode() {
415 return getKey().hashCode();
416 }
417
418 @Override
419 public boolean equals(Object obj) {
420 if (obj instanceof Map.Entry) {
421 final Object key = ((Map.Entry) obj).getKey();
422 final Object val = ((Map.Entry) obj).getValue();
423 if (key instanceof String && val instanceof Ref) {
424 final Ref" href="../../../../org/eclipse/jgit/lib/Ref.html#Ref">Ref r = (Ref) val;
425 if (r.getName().equals(ref.getName())) {
426 final ObjectId a = r.getObjectId();
427 final ObjectId b = ref.getObjectId();
428 if (a != null && b != null && AnyObjectId.equals(a, b))
429 return true;
430 }
431 }
432 }
433 return false;
434 }
435
436 @Override
437 public String toString() {
438 return ref.toString();
439 }
440 }
441 }