3535import hudson .util .CopyOnWriteMap ;
3636import java .io .File ;
3737import java .io .IOException ;
38- import java .util .AbstractCollection ;
3938import java .util .AbstractMap ;
40- import java .util .AbstractSet ;
4139import java .util .Collection ;
4240import java .util .Collections ;
4341import java .util .Comparator ;
4644import java .util .NoSuchElementException ;
4745import java .util .Set ;
4846import java .util .SortedMap ;
49- import java .util .Spliterator ;
50- import java .util .Spliterators ;
5147import java .util .TreeMap ;
52- import java .util .function .IntConsumer ;
5348import java .util .function .IntPredicate ;
5449import java .util .logging .Level ;
5550import java .util .logging .Logger ;
10196public abstract class AbstractLazyLoadRunMap <R > extends AbstractMap <Integer , R > implements SortedMap <Integer , R > {
10297 private final CopyOnWriteMap .Tree <Integer , BuildReference <R >> core = new CopyOnWriteMap .Tree <>(
10398 Collections .reverseOrder ());
104-
105- private LazyLoadRunMapEntrySet <R > entrySet = new LazyLoadRunMapEntrySet <>(this );
106-
107- private transient volatile Set <Integer > keySet ;
108- private transient volatile Collection <R > values ;
99+ private final BuildReferenceMapAdapter <R > adapter = new BuildReferenceMapAdapter <>(core ,
100+ this ::resolveBuildRef , this ::getNumberOf , this ::getBuildClass ) {
101+ @ Override
102+ protected boolean removeValue (R value ) {
103+ return AbstractLazyLoadRunMap .this .removeValue (value );
104+ }
105+ };
109106
110107 @ Override
111108 public Set <Integer > keySet () {
112- Set <Integer > ks = keySet ;
113- if (ks == null ) {
114- ks = new AbstractSet <>() {
115- @ Override
116- public Iterator <Integer > iterator () {
117- return new Iterator () {
118- private final Iterator <Entry <Integer , R >> it = entrySet ().iterator ();
119-
120- @ Override
121- public boolean hasNext () {
122- return it .hasNext ();
123- }
124-
125- @ Override
126- public Integer next () {
127- return it .next ().getKey ();
128- }
129-
130- @ Override
131- public void remove () {
132- it .remove ();
133- }
134- };
135- }
136-
137- @ Override
138- public Spliterator <Integer > spliterator () {
139- return new Spliterators .AbstractIntSpliterator (
140- Long .MAX_VALUE ,
141- Spliterator .DISTINCT | Spliterator .ORDERED | Spliterator .SORTED ) {
142- private final Iterator <Integer > it = iterator ();
143-
144- @ Override
145- public boolean tryAdvance (IntConsumer action ) {
146- if (action == null ) {
147- throw new NullPointerException ();
148- }
149- if (it .hasNext ()) {
150- action .accept (it .next ());
151- return true ;
152- }
153- return false ;
154- }
155-
156- @ Override
157- public Comparator <Integer > getComparator () {
158- return Collections .reverseOrder ();
159- }
160- };
161- }
162-
163- @ Override
164- public int size () {
165- return AbstractLazyLoadRunMap .this .size ();
166- }
167-
168- @ Override
169- public boolean isEmpty () {
170- return AbstractLazyLoadRunMap .this .isEmpty ();
171- }
172-
173- @ Override
174- public void clear () {
175- AbstractLazyLoadRunMap .this .clear ();
176- }
177-
178- @ Override
179- public boolean contains (Object k ) {
180- return AbstractLazyLoadRunMap .this .containsKey (k );
181- }
182- };
183- keySet = ks ;
184- }
185- return ks ;
109+ return adapter .keySet ();
186110 }
187111
188112 @ Override
189113 public Collection <R > values () {
190- Collection <R > vals = values ;
191- if (vals == null ) {
192- vals = new AbstractCollection <>() {
193- @ Override
194- public Iterator <R > iterator () {
195- return new Iterator <>() {
196- private final Iterator <Entry <Integer , R >> it = entrySet ().iterator ();
197-
198- @ Override
199- public boolean hasNext () {
200- return it .hasNext ();
201- }
202-
203- @ Override
204- public R next () {
205- return it .next ().getValue ();
206- }
207-
208- @ Override
209- public void remove () {
210- it .remove ();
211- }
212- };
213- }
214-
215- @ Override
216- public Spliterator <R > spliterator () {
217- return Spliterators .spliteratorUnknownSize (
218- iterator (), Spliterator .DISTINCT | Spliterator .ORDERED );
219- }
220-
221- @ Override
222- public int size () {
223- return AbstractLazyLoadRunMap .this .size ();
224- }
225-
226- @ Override
227- public boolean isEmpty () {
228- return AbstractLazyLoadRunMap .this .isEmpty ();
229- }
230-
231- @ Override
232- public void clear () {
233- AbstractLazyLoadRunMap .this .clear ();
234- }
114+ return adapter .values ();
115+ }
235116
236- @ Override
237- public boolean contains (Object v ) {
238- return AbstractLazyLoadRunMap .this .containsValue (v );
239- }
240- };
241- values = vals ;
242- }
243- return vals ;
117+ @ Override
118+ public Set <Entry <Integer , R >> entrySet () {
119+ assert baseDirInitialized ();
120+ return adapter .entrySet ();
244121 }
245122
246123 /**
@@ -354,18 +231,22 @@ public final void recognizeNumber(int buildNumber) {
354231
355232 @ Override
356233 public Comparator <? super Integer > comparator () {
357- return Collections . reverseOrder ();
234+ return core . comparator ();
358235 }
359236
360237 @ Override
361238 public boolean isEmpty () {
362- return search ( Integer . MAX_VALUE , DESC ) == null ;
239+ return adapter . isEmpty () ;
363240 }
364241
365242 @ Override
366- public Set <Entry <Integer , R >> entrySet () {
367- assert baseDirInitialized ();
368- return entrySet ;
243+ public boolean containsKey (Object value ) {
244+ return adapter .containsKey (value );
245+ }
246+
247+ @ Override
248+ public boolean containsValue (Object value ) {
249+ return adapter .containsValue (value );
369250 }
370251
371252 /**
@@ -379,7 +260,7 @@ public SortedMap<Integer, R> getLoadedBuilds() {
379260 res .put (entry .getKey (), buildRef );
380261 }
381262 }
382- return Collections . unmodifiableSortedMap ( new BuildReferenceMapAdapter <>(this , res ) );
263+ return new BuildReferenceMapAdapter <>(res , this :: resolveBuildRef , this :: getNumberOf , this :: getBuildClass );
383264 }
384265
385266 /**
@@ -390,33 +271,17 @@ public SortedMap<Integer, R> getLoadedBuilds() {
390271 */
391272 @ Override
392273 public SortedMap <Integer , R > subMap (Integer fromKey , Integer toKey ) {
393- // TODO: if this method can produce a lazy map, that'd be wonderful
394- // because due to the lack of floor/ceil/higher/lower kind of methods
395- // to look up keys in SortedMap, various places of Jenkins rely on
396- // subMap+firstKey/lastKey combo.
397-
398- R start = search (fromKey , DESC );
399- if (start == null ) return EMPTY_SORTED_MAP ;
400-
401- R end = search (toKey , ASC );
402- if (end == null ) return EMPTY_SORTED_MAP ;
403-
404- for (R i = start ; i != end ; ) {
405- i = search (getNumberOf (i ) - 1 , DESC );
406- assert i != null ;
407- }
408-
409- return Collections .unmodifiableSortedMap (new BuildReferenceMapAdapter <>(this , core .subMap (fromKey , toKey )));
274+ return adapter .subMap (fromKey , toKey );
410275 }
411276
412277 @ Override
413278 public SortedMap <Integer , R > headMap (Integer toKey ) {
414- return subMap ( Integer . MAX_VALUE , toKey );
279+ return adapter . headMap ( toKey );
415280 }
416281
417282 @ Override
418283 public SortedMap <Integer , R > tailMap (Integer fromKey ) {
419- return subMap (fromKey , Integer . MIN_VALUE );
284+ return adapter . tailMap (fromKey );
420285 }
421286
422287 @ Override
@@ -443,11 +308,7 @@ public R oldestBuild() {
443308
444309 @ Override
445310 public R get (Object key ) {
446- if (key instanceof Integer ) {
447- int n = (Integer ) key ;
448- return get (n );
449- }
450- return super .get (key );
311+ return adapter .get (key );
451312 }
452313
453314 public R get (int n ) {
@@ -552,7 +413,7 @@ private R resolveBuildRef(BuildReference<R> ref) {
552413 }
553414
554415 public R getByNumber (int n ) {
555- return resolveBuildRef ( core .get (n ) );
416+ return adapter .get (n );
556417 }
557418
558419 /**
@@ -597,14 +458,9 @@ public synchronized void putAll(Map<? extends Integer, ? extends R> newData) {
597458 core .putAll (newWrapperData );
598459 }
599460
600- /**
601- * Return underlining {@link BuildReference} core map.
602- *
603- * @return
604- * full build reference map.
605- */
606- /*package*/ SortedMap <Integer , BuildReference <R >> all () {
607- return core ;
461+ @ Override
462+ public R remove (Object key ) {
463+ return adapter .remove (key );
608464 }
609465
610466 /**
@@ -652,7 +508,6 @@ protected BuildReference<R> createReference(R r) {
652508 return new BuildReference <>(getIdOf (r ), r );
653509 }
654510
655-
656511 /**
657512 * Parses {@code R} instance from data in the specified directory.
658513 *
@@ -664,6 +519,8 @@ protected BuildReference<R> createReference(R r) {
664519 */
665520 protected abstract R retrieve (File dir ) throws IOException ;
666521
522+ protected abstract Class <R > getBuildClass ();
523+
667524 public synchronized boolean removeValue (R run ) {
668525 return core .remove (getNumberOf (run )) != null ;
669526 }
@@ -694,7 +551,5 @@ public enum Direction {
694551 ASC , DESC , EXACT
695552 }
696553
697- private static final SortedMap EMPTY_SORTED_MAP = Collections .unmodifiableSortedMap (new TreeMap ());
698-
699554 static final Logger LOGGER = Logger .getLogger (AbstractLazyLoadRunMap .class .getName ());
700555}
0 commit comments