• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ben-manes / caffeine / #4915

22 Jun 2025 11:32PM UTC coverage: 99.974% (-0.03%) from 100.0%
#4915

push

github

ben-manes
increase branch coverage

3676 of 3814 branches covered (96.38%)

4 of 4 new or added lines in 2 files covered. (100.0%)

2 existing lines in 1 file now uncovered.

7734 of 7736 relevant lines covered (99.97%)

1.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.92
/jcache/src/main/java/com/github/benmanes/caffeine/jcache/configuration/CaffeineConfiguration.java
1
/*
2
 * Copyright 2015 Ben Manes. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.github.benmanes.caffeine.jcache.configuration;
17

18
import static java.util.Objects.requireNonNull;
19

20
import java.util.Iterator;
21
import java.util.Objects;
22
import java.util.Optional;
23
import java.util.OptionalLong;
24
import java.util.Spliterator;
25
import java.util.concurrent.Executor;
26
import java.util.concurrent.ForkJoinPool;
27

28
import javax.cache.configuration.CacheEntryListenerConfiguration;
29
import javax.cache.configuration.CompleteConfiguration;
30
import javax.cache.configuration.Factory;
31
import javax.cache.configuration.MutableConfiguration;
32
import javax.cache.expiry.ExpiryPolicy;
33
import javax.cache.integration.CacheLoader;
34
import javax.cache.integration.CacheWriter;
35

36
import org.jspecify.annotations.NullMarked;
37
import org.jspecify.annotations.Nullable;
38

39
import com.github.benmanes.caffeine.cache.Expiry;
40
import com.github.benmanes.caffeine.cache.Scheduler;
41
import com.github.benmanes.caffeine.cache.Ticker;
42
import com.github.benmanes.caffeine.cache.Weigher;
43
import com.github.benmanes.caffeine.jcache.copy.Copier;
44
import com.github.benmanes.caffeine.jcache.copy.JavaSerializationCopier;
45
import com.google.errorprone.annotations.CanIgnoreReturnValue;
46

47
/**
48
 * A JCache configuration with Caffeine specific settings.
49
 * <p>
50
 * The initial settings disable <code>store by value</code> so that entries are not copied when
51
 * crossing the {@link javax.cache.Cache} API boundary. If enabled and the {@link Copier} is not
52
 * explicitly set, then the {@link JavaSerializationCopier} will be used. This differs from
53
 * {@link MutableConfiguration} which enables <code>store by value</code> at construction.
54
 *
55
 * @author ben.manes@gmail.com (Ben Manes)
56
 */
57
@NullMarked
58
public final class CaffeineConfiguration<K, V> implements CompleteConfiguration<K, V> {
59
  private static final Factory<Scheduler> DISABLED_SCHEDULER = Scheduler::disabledScheduler;
1✔
60
  private static final Factory<Copier> JAVA_COPIER = JavaSerializationCopier::new;
1✔
61
  private static final Factory<Executor> COMMON_POOL = ForkJoinPool::commonPool;
1✔
62
  private static final Factory<Ticker> SYSTEM_TICKER = Ticker::systemTicker;
1✔
63
  private static final long serialVersionUID = 1L;
64

65
  private final MutableConfiguration<K, V> delegate;
66
  private final boolean readOnly;
67

68
  private @Nullable Factory<Weigher<K, V>> weigherFactory;
69
  private @Nullable Factory<Expiry<K, V>> expiryFactory;
70

71
  private Factory<Scheduler> schedulerFactory;
72
  private Factory<Executor> executorFactory;
73
  private Factory<Copier> copierFactory;
74
  private Factory<Ticker> tickerFactory;
75

76
  private @Nullable Long refreshAfterWriteNanos;
77
  private @Nullable Long expireAfterAccessNanos;
78
  private @Nullable Long expireAfterWriteNanos;
79
  private @Nullable Long maximumWeight;
80
  private @Nullable Long maximumSize;
81
  private boolean nativeStatistics;
82

83
  public CaffeineConfiguration() {
1✔
84
    delegate = new MutableConfiguration<>();
1✔
85
    delegate.setStoreByValue(false);
1✔
86
    schedulerFactory = DISABLED_SCHEDULER;
1✔
87
    tickerFactory = SYSTEM_TICKER;
1✔
88
    executorFactory = COMMON_POOL;
1✔
89
    copierFactory = JAVA_COPIER;
1✔
90
    readOnly = false;
1✔
91
  }
1✔
92

93
  /** Returns a modifiable copy of the configuration. */
94
  public CaffeineConfiguration(CompleteConfiguration<K, V> configuration) {
95
    this(configuration, /* readOnly= */ false);
1✔
96
  }
1✔
97

98
  private CaffeineConfiguration(CompleteConfiguration<K, V> configuration, boolean readOnly) {
1✔
99
    delegate = new MutableConfiguration<>(configuration);
1✔
100
    if (configuration instanceof CaffeineConfiguration<?, ?>) {
1✔
101
      var config = (CaffeineConfiguration<K, V>) configuration;
1✔
102
      refreshAfterWriteNanos = config.refreshAfterWriteNanos;
1✔
103
      expireAfterAccessNanos = config.expireAfterAccessNanos;
1✔
104
      expireAfterWriteNanos = config.expireAfterWriteNanos;
1✔
105
      nativeStatistics = config.nativeStatistics;
1✔
106
      schedulerFactory = config.schedulerFactory;
1✔
107
      executorFactory = config.executorFactory;
1✔
108
      expiryFactory = config.expiryFactory;
1✔
109
      copierFactory = config.copierFactory;
1✔
110
      tickerFactory = config.tickerFactory;
1✔
111
      weigherFactory = config.weigherFactory;
1✔
112
      maximumWeight = config.maximumWeight;
1✔
113
      maximumSize = config.maximumSize;
1✔
114
    } else {
1✔
115
      schedulerFactory = DISABLED_SCHEDULER;
1✔
116
      tickerFactory = SYSTEM_TICKER;
1✔
117
      executorFactory = COMMON_POOL;
1✔
118
      copierFactory = JAVA_COPIER;
1✔
119
    }
120
    this.readOnly = readOnly;
1✔
121
  }
1✔
122

123
  /** Returns an unmodifiable copy of this configuration. */
124
  public CaffeineConfiguration<K, V> immutableCopy() {
125
    return new CaffeineConfiguration<>(this, /* readOnly= */ true);
1✔
126
  }
127

128
  private void checkIfReadOnly() {
129
    if (readOnly) {
1✔
130
      throw new UnsupportedOperationException();
1✔
131
    }
132
  }
1✔
133

134
  @Override
135
  public Class<K> getKeyType() {
136
    return delegate.getKeyType();
1✔
137
  }
138

139
  @Override
140
  public Class<V> getValueType() {
141
    return delegate.getValueType();
1✔
142
  }
143

144
  /** See {@link MutableConfiguration#setTypes}. */
145
  @CanIgnoreReturnValue
146
  public CaffeineConfiguration<K, V> setTypes(Class<K> keyType, Class<V> valueType) {
147
    checkIfReadOnly();
1✔
148
    delegate.setTypes(keyType, valueType);
1✔
149
    return this;
1✔
150
  }
151

152
  @Override
153
  public Iterable<CacheEntryListenerConfiguration<K, V>> getCacheEntryListenerConfigurations() {
154
    return new UnmodifiableIterable<>(delegate.getCacheEntryListenerConfigurations());
1✔
155
  }
156

157
  /** See {@link MutableConfiguration#addCacheEntryListenerConfiguration}. */
158
  @CanIgnoreReturnValue
159
  public CaffeineConfiguration<K, V> addCacheEntryListenerConfiguration(
160
      CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration) {
161
    checkIfReadOnly();
1✔
162
    delegate.addCacheEntryListenerConfiguration(cacheEntryListenerConfiguration);
1✔
163
    return this;
1✔
164
  }
165

166
  /** See {@link MutableConfiguration#removeCacheEntryListenerConfiguration}. */
167
  @CanIgnoreReturnValue
168
  public CaffeineConfiguration<K, V> removeCacheEntryListenerConfiguration(
169
      CacheEntryListenerConfiguration<K, V> cacheEntryListenerConfiguration) {
170
    checkIfReadOnly();
1✔
171
    delegate.removeCacheEntryListenerConfiguration(cacheEntryListenerConfiguration);
1✔
172
    return this;
1✔
173
  }
174

175
  @Override
176
  public @Nullable Factory<CacheLoader<K, V>> getCacheLoaderFactory() {
177
    return delegate.getCacheLoaderFactory();
1✔
178
  }
179

180
  /** See {@link MutableConfiguration#setCacheLoaderFactory}. */
181
  @CanIgnoreReturnValue
182
  public CaffeineConfiguration<K, V> setCacheLoaderFactory(
183
      @Nullable Factory<? extends CacheLoader<K, V>> factory) {
184
    checkIfReadOnly();
1✔
185
    delegate.setCacheLoaderFactory(factory);
1✔
186
    return this;
1✔
187
  }
188

189
  @Override
190
  public @Nullable Factory<CacheWriter<? super K, ? super V>> getCacheWriterFactory() {
191
    return delegate.getCacheWriterFactory();
1✔
192
  }
193

194
  /** Returns a writer created by the configured factory or null if not set. */
195
  public @Nullable CacheWriter<K , V> getCacheWriter() {
196
    var factory = delegate.getCacheWriterFactory();
1✔
197
    if (factory != null) {
1✔
198
      @SuppressWarnings("unchecked")
199
      var writer = (CacheWriter<K, V>) factory.create();
1✔
200
      return writer;
1✔
201
    }
202
    return null;
1✔
203
  }
204

205
  /** Returns if the cache writer factory is specified. */
206
  public boolean hasCacheWriter() {
207
    return getCacheWriterFactory() != null;
1✔
208
  }
209

210
  /** See {@link MutableConfiguration#setCacheWriterFactory}. */
211
  @CanIgnoreReturnValue
212
  public CaffeineConfiguration<K, V> setCacheWriterFactory(
213
      @Nullable Factory<? extends CacheWriter<? super K, ? super V>> factory) {
214
    checkIfReadOnly();
1✔
215
    delegate.setCacheWriterFactory(factory);
1✔
216
    return this;
1✔
217
  }
218

219
  @Override
220
  public Factory<ExpiryPolicy> getExpiryPolicyFactory() {
221
    return delegate.getExpiryPolicyFactory();
1✔
222
  }
223

224
  /** See {@link MutableConfiguration#setExpiryPolicyFactory}. */
225
  @CanIgnoreReturnValue
226
  public CaffeineConfiguration<K, V> setExpiryPolicyFactory(
227
      @Nullable Factory<? extends ExpiryPolicy> factory) {
228
    checkIfReadOnly();
1✔
229
    delegate.setExpiryPolicyFactory(factory);
1✔
230
    return this;
1✔
231
  }
232

233
  @Override
234
  public boolean isReadThrough() {
235
    return delegate.isReadThrough();
1✔
236
  }
237

238
  /** See {@link MutableConfiguration#setReadThrough}. */
239
  @CanIgnoreReturnValue
240
  public CaffeineConfiguration<K, V> setReadThrough(boolean isReadThrough) {
241
    checkIfReadOnly();
1✔
242
    delegate.setReadThrough(isReadThrough);
1✔
243
    return this;
1✔
244
  }
245

246
  @Override
247
  public boolean isWriteThrough() {
248
    return delegate.isWriteThrough();
1✔
249
  }
250

251
  /** See {@link MutableConfiguration#setWriteThrough}. */
252
  @CanIgnoreReturnValue
253
  public CaffeineConfiguration<K, V> setWriteThrough(boolean isWriteThrough) {
254
    checkIfReadOnly();
1✔
255
    delegate.setWriteThrough(isWriteThrough);
1✔
256
    return this;
1✔
257
  }
258

259
  @Override
260
  public boolean isStoreByValue() {
261
    return delegate.isStoreByValue();
1✔
262
  }
263

264
  /** See {@link MutableConfiguration#setStoreByValue}. */
265
  @CanIgnoreReturnValue
266
  public CaffeineConfiguration<K, V> setStoreByValue(boolean isStoreByValue) {
267
    checkIfReadOnly();
1✔
268
    delegate.setStoreByValue(isStoreByValue);
1✔
269
    return this;
1✔
270
  }
271

272
  /**
273
   * Checks whether native statistics collection is enabled in this cache.
274
   * <p>
275
   * The default value is <code>false</code>.
276
   *
277
   * @return true if native statistics collection is enabled
278
   */
279
  public boolean isNativeStatisticsEnabled() {
280
    return nativeStatistics;
1✔
281
  }
282

283
  /**
284
   * Sets whether native statistics gathering is enabled on a cache.
285
   *
286
   * @param enabled true to enable native statistics, false to disable.
287
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
288
   */
289
  @CanIgnoreReturnValue
290
  public CaffeineConfiguration<K, V> setNativeStatisticsEnabled(boolean enabled) {
291
    checkIfReadOnly();
1✔
292
    this.nativeStatistics = enabled;
1✔
293
    return this;
1✔
294
  }
295

296
  @Override
297
  public boolean isStatisticsEnabled() {
298
    return delegate.isStatisticsEnabled();
1✔
299
  }
300

301
  /** See {@link MutableConfiguration#setStatisticsEnabled}. */
302
  @CanIgnoreReturnValue
303
  public CaffeineConfiguration<K, V> setStatisticsEnabled(boolean enabled) {
304
    checkIfReadOnly();
1✔
305
    delegate.setStatisticsEnabled(enabled);
1✔
306
    return this;
1✔
307
  }
308

309
  /** See {@link CompleteConfiguration#isManagementEnabled}. */
310
  @Override
311
  public boolean isManagementEnabled() {
312
    return delegate.isManagementEnabled();
1✔
313
  }
314

315
  /** See {@link MutableConfiguration#setManagementEnabled}. */
316
  @CanIgnoreReturnValue
317
  public CaffeineConfiguration<K, V> setManagementEnabled(boolean enabled) {
318
    checkIfReadOnly();
1✔
319
    delegate.setManagementEnabled(enabled);
1✔
320
    return this;
1✔
321
  }
322

323
  /**
324
   * Returns the {@link Factory} for the {@link Copier} to be used for the cache.
325
   *
326
   * @return the {@link Factory} for the {@link Copier}
327
   */
328
  public Factory<Copier> getCopierFactory() {
329
    return copierFactory;
1✔
330
  }
331

332
  /**
333
   * Set the {@link Factory} for the {@link Copier}.
334
   *
335
   * @param factory the {@link Copier} {@link Factory}
336
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
337
   */
338
  @CanIgnoreReturnValue
339
  public CaffeineConfiguration<K, V> setCopierFactory(Factory<Copier> factory) {
340
    checkIfReadOnly();
1✔
341
    copierFactory = requireNonNull(factory);
1✔
342
    return this;
1✔
343
  }
344

345
  /**
346
   * Returns the {@link Factory} for the {@link Scheduler} to be used for the cache.
347
   *
348
   * @return the {@link Factory} for the {@link Scheduler}
349
   */
350
  public Factory<Scheduler> getSchedulerFactory() {
351
    return schedulerFactory;
1✔
352
  }
353

354
  /**
355
   * Set the {@link Factory} for the {@link Scheduler}.
356
   *
357
   * @param factory the {@link Scheduler} {@link Factory}
358
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
359
   */
360
  @CanIgnoreReturnValue
361
  public CaffeineConfiguration<K, V> setSchedulerFactory(Factory<Scheduler> factory) {
362
    checkIfReadOnly();
1✔
363
    schedulerFactory = requireNonNull(factory);
1✔
364
    return this;
1✔
365
  }
366

367
  /**
368
   * Returns the {@link Factory} for the {@link Ticker} to be used for the cache.
369
   *
370
   * @return the {@link Factory} for the {@link Ticker}
371
   */
372
  public Factory<Ticker> getTickerFactory() {
373
    return tickerFactory;
1✔
374
  }
375

376
  /**
377
   * Set the {@link Factory} for the {@link Ticker}.
378
   *
379
   * @param factory the {@link Ticker} {@link Factory}
380
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
381
   */
382
  @CanIgnoreReturnValue
383
  public CaffeineConfiguration<K, V> setTickerFactory(Factory<Ticker> factory) {
384
    checkIfReadOnly();
1✔
385
    tickerFactory = requireNonNull(factory);
1✔
386
    return this;
1✔
387
  }
388

389
  /**
390
   * Returns the {@link Factory} for the {@link Executor} to be used for the cache.
391
   *
392
   * @return the {@link Factory} for the {@link Executor}
393
   */
394
  public Factory<Executor> getExecutorFactory() {
395
    return executorFactory;
1✔
396
  }
397

398
  /**
399
   * Set the {@link Factory} for the {@link Executor}.
400
   *
401
   * @param factory the {@link Executor} {@link Factory}
402
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
403
   */
404
  @CanIgnoreReturnValue
405
  public CaffeineConfiguration<K, V> setExecutorFactory(Factory<Executor> factory) {
406
    checkIfReadOnly();
1✔
407
    executorFactory = requireNonNull(factory);
1✔
408
    return this;
1✔
409
  }
410

411
  /**
412
   * Returns the refresh after write in nanoseconds.
413
   *
414
   * @return the duration in nanoseconds
415
   */
416
  public OptionalLong getRefreshAfterWrite() {
417
    return (refreshAfterWriteNanos == null)
1✔
418
        ? OptionalLong.empty()
1✔
419
        : OptionalLong.of(refreshAfterWriteNanos);
1✔
420
  }
421

422
  /**
423
   * Set the refresh after write in nanoseconds.
424
   *
425
   * @param refreshAfterWriteNanos the duration in nanoseconds
426
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
427
   */
428
  @CanIgnoreReturnValue
429
  public CaffeineConfiguration<K, V> setRefreshAfterWrite(OptionalLong refreshAfterWriteNanos) {
430
    checkIfReadOnly();
1✔
431
    this.refreshAfterWriteNanos = refreshAfterWriteNanos.isPresent()
1✔
432
        ? refreshAfterWriteNanos.getAsLong()
1✔
433
        : null;
1✔
434
    return this;
1✔
435
  }
436

437
  /**
438
   * Returns the expire after write in nanoseconds.
439
   *
440
   * @return the duration in nanoseconds
441
   */
442
  public OptionalLong getExpireAfterWrite() {
443
    return (expireAfterWriteNanos == null)
1✔
444
        ? OptionalLong.empty()
1✔
445
        : OptionalLong.of(expireAfterWriteNanos);
1✔
446
  }
447

448
  /**
449
   * Set the expire after write in nanoseconds.
450
   *
451
   * @param expireAfterWriteNanos the duration in nanoseconds
452
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
453
   */
454
  @CanIgnoreReturnValue
455
  public CaffeineConfiguration<K, V> setExpireAfterWrite(OptionalLong expireAfterWriteNanos) {
456
    checkIfReadOnly();
1✔
457
    this.expireAfterWriteNanos = expireAfterWriteNanos.isPresent()
1✔
458
        ? expireAfterWriteNanos.getAsLong()
1✔
459
        : null;
1✔
460
    return this;
1✔
461
  }
462

463
  /**
464
   * Returns the expire after access in nanoseconds.
465
   *
466
   * @return the duration in nanoseconds
467
   */
468
  public OptionalLong getExpireAfterAccess() {
469
    return (expireAfterAccessNanos == null)
1✔
470
        ? OptionalLong.empty()
1✔
471
        : OptionalLong.of(expireAfterAccessNanos);
1✔
472
  }
473

474
  /**
475
   * Set the expire after write in nanoseconds.
476
   *
477
   * @param expireAfterAccessNanos the duration in nanoseconds
478
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
479
   */
480
  @CanIgnoreReturnValue
481
  public CaffeineConfiguration<K, V> setExpireAfterAccess(OptionalLong expireAfterAccessNanos) {
482
    checkIfReadOnly();
1✔
483
    this.expireAfterAccessNanos = expireAfterAccessNanos.isPresent()
1✔
484
        ? expireAfterAccessNanos.getAsLong()
1✔
485
        : null;
1✔
486
    return this;
1✔
487
  }
488

489
  /**
490
   * Returns the {@link Factory} for the {@link Expiry} to be used for the cache.
491
   *
492
   * @return the {@link Factory} for the {@link Expiry}
493
   */
494
  public Optional<Factory<Expiry<K, V>>> getExpiryFactory() {
495
    return Optional.ofNullable(expiryFactory);
1✔
496
  }
497

498
  /**
499
   * Set the {@link Factory} for the {@link Expiry}.
500
   *
501
   * @param factory the {@link Expiry} {@link Factory}
502
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
503
   */
504
  @CanIgnoreReturnValue
505
  @SuppressWarnings("unchecked")
506
  public CaffeineConfiguration<K, V> setExpiryFactory(
507
      Optional<Factory<? extends Expiry<K, V>>> factory) {
508
    checkIfReadOnly();
1✔
509
    expiryFactory = (Factory<Expiry<K, V>>) factory.orElse(null);
1✔
510
    return this;
1✔
511
  }
512

513
  /**
514
   * Returns the maximum size to be used for the cache.
515
   *
516
   * @return the maximum size
517
   */
518
  public OptionalLong getMaximumSize() {
519
    return (maximumSize == null)
1✔
520
        ? OptionalLong.empty()
1✔
521
        : OptionalLong.of(maximumSize);
1✔
522
  }
523

524
  /**
525
   * Set the maximum size.
526
   *
527
   * @param maximumSize the maximum size
528
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
529
   */
530
  @CanIgnoreReturnValue
531
  public CaffeineConfiguration<K, V> setMaximumSize(OptionalLong maximumSize) {
532
    checkIfReadOnly();
1✔
533
    this.maximumSize = maximumSize.isPresent()
1✔
534
        ? maximumSize.getAsLong()
1✔
535
        : null;
1✔
536
    return this;
1✔
537
  }
538

539
  /**
540
   * Returns the maximum weight to be used for the cache.
541
   *
542
   * @return the maximum weight
543
   */
544
  public OptionalLong getMaximumWeight() {
545
    return (maximumWeight == null)
1✔
546
        ? OptionalLong.empty()
1✔
547
        : OptionalLong.of(maximumWeight);
1✔
548
  }
549

550
  /**
551
   * Set the maximum weight.
552
   *
553
   * @param maximumWeight the maximum weighted size
554
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
555
   */
556
  @CanIgnoreReturnValue
557
  public CaffeineConfiguration<K, V> setMaximumWeight(OptionalLong maximumWeight) {
558
    checkIfReadOnly();
1✔
559
    this.maximumWeight = maximumWeight.isPresent()
1✔
560
        ? maximumWeight.getAsLong()
1✔
561
        : null;
1✔
562
    return this;
1✔
563
  }
564

565
  /**
566
   * Returns the {@link Factory} for the {@link Weigher} to be used for the cache.
567
   *
568
   * @return the {@link Factory} for the {@link Weigher}
569
   */
570
  public Optional<Factory<Weigher<K, V>>> getWeigherFactory() {
571
    return Optional.ofNullable(weigherFactory);
1✔
572
  }
573

574
  /**
575
   * Set the {@link Factory} for the {@link Weigher}.
576
   *
577
   * @param factory the {@link Weigher} {@link Factory}
578
   * @return the {@link CaffeineConfiguration} to permit fluent-style method calls
579
   */
580
  @CanIgnoreReturnValue
581
  @SuppressWarnings("unchecked")
582
  public CaffeineConfiguration<K, V> setWeigherFactory(
583
      Optional<Factory<? extends Weigher<K, V>>> factory) {
584
    checkIfReadOnly();
1✔
585
    weigherFactory = (Factory<Weigher<K, V>>) factory.orElse(null);
1✔
586
    return this;
1✔
587
  }
588

589
  @Override
590
  public boolean equals(@Nullable Object o) {
591
    if (o == this) {
1!
UNCOV
592
      return true;
×
593
    } else if (!(o instanceof CaffeineConfiguration<?, ?>)) {
1!
UNCOV
594
      return false;
×
595
    }
596
    var config = (CaffeineConfiguration<?, ?>) o;
1✔
597
    return Objects.equals(refreshAfterWriteNanos, config.refreshAfterWriteNanos)
1✔
598
        && Objects.equals(expireAfterAccessNanos, config.expireAfterAccessNanos)
1!
599
        && Objects.equals(expireAfterWriteNanos, config.expireAfterWriteNanos)
1!
600
        && Objects.equals(schedulerFactory, config.schedulerFactory)
1!
601
        && Objects.equals(executorFactory, config.executorFactory)
1!
602
        && Objects.equals(weigherFactory, config.weigherFactory)
1!
603
        && Objects.equals(copierFactory, config.copierFactory)
1!
604
        && Objects.equals(maximumWeight, config.maximumWeight)
1!
605
        && Objects.equals(tickerFactory, config.tickerFactory)
1!
606
        && Objects.equals(maximumSize, config.maximumSize)
1!
607
        && delegate.equals(config.delegate);
1✔
608
  }
609

610
  @Override
611
  public int hashCode() {
612
    return delegate.hashCode();
1✔
613
  }
614

615
  private static final class UnmodifiableIterable<E> implements Iterable<E> {
616
    private final Iterable<E> delegate;
617

618
    private UnmodifiableIterable(Iterable<E> delegate) {
1✔
619
      this.delegate = delegate;
1✔
620
    }
1✔
621
    @Override public Iterator<E> iterator() {
622
      var iterator = delegate.iterator();
1✔
623
      return new Iterator<>() {
1✔
624
        @Override public boolean hasNext() {
625
          return iterator.hasNext();
1✔
626
        }
627
        @Override public E next() {
628
          return iterator.next();
1✔
629
        }
630
      };
631
    }
632
    @Override public Spliterator<E> spliterator() {
633
      return delegate.spliterator();
1✔
634
    }
635
    @Override public String toString() {
636
      return delegate.toString();
1✔
637
    }
638
  }
639
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc