All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cache2k.Cache2kBuilder Maven / Gradle / Ivy

Go to download

A light weight and high performance Java caching library. Android and Java 6 compatible. This artifact contains the official API of cache2k.

There is a newer version: 2.6.1.Final
Show newest version
package org.cache2k;

/*
 * #%L
 * cache2k API
 * %%
 * Copyright (C) 2000 - 2021 headissue GmbH, Munich
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import org.cache2k.io.AsyncBulkCacheLoader;
import org.cache2k.io.BulkCacheLoader;
import org.cache2k.operation.Scheduler;
import org.cache2k.operation.TimeReference;
import org.cache2k.annotation.Nullable;
import org.cache2k.config.Cache2kConfig;
import org.cache2k.config.CacheType;
import org.cache2k.config.ConfigBean;
import org.cache2k.config.ConfigBuilder;
import org.cache2k.config.WithSection;
import org.cache2k.config.SectionBuilder;
import org.cache2k.config.CustomizationReferenceSupplier;
import org.cache2k.config.CustomizationSupplier;
import org.cache2k.config.ConfigSection;
import org.cache2k.config.ToggleFeature;
import org.cache2k.event.CacheClosedListener;
import org.cache2k.expiry.ExpiryPolicy;
import org.cache2k.event.CacheEntryOperationListener;
import org.cache2k.io.AdvancedCacheLoader;
import org.cache2k.io.AsyncCacheLoader;
import org.cache2k.io.CacheLoader;
import org.cache2k.io.CacheWriter;
import org.cache2k.io.ExceptionPropagator;
import org.cache2k.io.ResiliencePolicy;
import org.cache2k.io.CacheLoaderException;
import org.cache2k.operation.Weigher;
import org.cache2k.processor.MutableCacheEntry;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.time.Duration;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * Builder to create a {@link Cache} instance. The usage is:
 *
 * 
{@code
 *    Cache> c =
 *      new Cache2kBuilder>() {}
 *        .name("myCache")
 *        .eternal(true)
 *        .build();
 * }
* *

Caches belong to a cache manager. If no cache manager is set explicitly via * {@link #manager} the default cache manager will be used, as defined by * {@link CacheManager#getInstance()}. * *

To create a cache from a known configuration in a specified cache manager, use: * *

{@code
 *   CacheManager manager = ...
 *   CacheConfiguration> config = ...
 *
 *   Cache> c =
 *     Cache2kBuilder.of(config)
 *       .manager(manager)
 *       .build();
 * }
* *

To create a cache without type parameters or {@code Cache}, use * {@link Cache2kBuilder#forUnknownTypes()}. * *

This builder can also be used to alter and build a configuration object that * can be retrieved with {@link #config()} * * @author Jens Wilke * @since 1.0 */ @SuppressWarnings("nullness") public class Cache2kBuilder implements ConfigBuilder, Cache2kConfig>, DataAware { private static final String MSG_NO_TYPES = "Use Cache2kBuilder.forUnknownTypes(), to construct a builder with no key and value types"; /** * Create a new cache builder for a cache that has no type restrictions * or to set the type information later via the builder methods {@link #keyType} or * {@link #valueType}. */ @SuppressWarnings({"unchecked", "rawtypes"}) public static Cache2kBuilder forUnknownTypes() { return new Cache2kBuilder(null, null); } /** * Create a new cache builder for key and value types of classes with no generic parameters. * * @see #keyType(Class) * @see #valueType(Class) */ public static Cache2kBuilder of(Class keyType, Class valueType) { return new Cache2kBuilder(CacheType.of(keyType), CacheType.of(valueType)); } /** * Create a builder from the configuration bean. The builder is not assigned * to a cache manager and any default configurations, if present, will not be * applied. */ public static Cache2kBuilder of(Cache2kConfig c) { Cache2kBuilder cb = new Cache2kBuilder(c); return cb; } private @Nullable CacheType keyType; private @Nullable CacheType valueType; private @Nullable Cache2kConfig config = null; private @Nullable CacheManager manager = null; private Cache2kBuilder(Cache2kConfig cfg) { withConfig(cfg); } /** * Constructor to override for the usage pattern: * *

{@code
   *    Cache> c =
   *      new Cache2kBuilder>() {}
   *        .name("myCache")
   *        .eternal(true)
   *        .build();
   * }
* * The builder extracts the generic type parameters from the anonymous subclass. */ @SuppressWarnings("unchecked") protected Cache2kBuilder() { Type t = this.getClass().getGenericSuperclass(); if (!(t instanceof ParameterizedType)) { throw new IllegalArgumentException(MSG_NO_TYPES); } Type[] types = ((ParameterizedType) t).getActualTypeArguments(); keyType = (CacheType) CacheType.of(types[0]); valueType = (CacheType) CacheType.of(types[1]); if (Object.class.equals(keyType.getType()) && Object.class.equals(valueType.getType())) { throw new IllegalArgumentException(MSG_NO_TYPES); } } private Cache2kBuilder(@Nullable CacheType keyType, @Nullable CacheType valueType) { this.keyType = keyType; this.valueType = valueType; } private void withConfig(Cache2kConfig cfg) { config = cfg; } /** * Bind to default manager if not set before. Read in default configuration. */ @SuppressWarnings("unchecked") private Cache2kConfig cfg() { if (config == null) { config = CacheManager.PROVIDER.getDefaultConfig(getManager()); if (keyType != null) { config.setKeyType(keyType); } if (valueType != null) { config.setValueType(valueType); } } return config; } /** * The manager, the created cache will belong to. If this is set, it must be the * first method called. * * @param manager The manager the created cache should belong to, * or {@code null} if the default cache manager should be used * @throws IllegalStateException if the manager is not provided immediately after the builder * is created. */ public final Cache2kBuilder manager(CacheManager manager) { if (this.manager != null) { throw new IllegalStateException("manager() must be first operation on builder."); } this.manager = manager; return this; } /** * The used type of the cache key. A suitable cache key must provide a useful * {@code equals} and {@code hashCode} method. Arrays are not valid for cache keys. * * @throws IllegalArgumentException in case the type is illegal * @see CacheType for a general discussion on types */ @SuppressWarnings("unchecked") public final Cache2kBuilder keyType(Class t) { Cache2kBuilder me = (Cache2kBuilder) this; me.cfg().setKeyType(CacheType.of(t)); return me; } /** * Sets the value type to use. Arrays are not supported. * * @throws IllegalArgumentException in case the type is illegal * @see CacheType for a general discussion on types */ @SuppressWarnings("unchecked") public final Cache2kBuilder valueType(Class t) { Cache2kBuilder me = (Cache2kBuilder) this; me.cfg().setValueType(CacheType.of(t)); return me; } /** * The used type of the cache key. A suitable cache key must provide a useful * {@code equals} and {@code hashCode} method. Arrays are not valid for cache keys. * * @throws IllegalArgumentException in case the type is illegal * @see CacheType for a general discussion on types */ @SuppressWarnings("unchecked") public final Cache2kBuilder keyType(CacheType t) { Cache2kBuilder me = (Cache2kBuilder) this; me.cfg().setKeyType(t); return me; } /** * Sets the value type to use. Arrays are not supported. * * @throws IllegalArgumentException in case the type is illegal * @see CacheType for a general discussion on types */ @SuppressWarnings("unchecked") public final Cache2kBuilder valueType(CacheType t) { Cache2kBuilder me = (Cache2kBuilder) this; me.cfg().setValueType(t); return me; } /** * Constructs a cache name out of the class name, a field name and a unique name identifying the * component in the application. Result example: * {@code webImagePool~com.example.ImagePool.id2Image} * *

See {@link #name(String)} for a general discussion about cache names. * * @param uniqueName unique name differentiating multiple components of the same type. * May be {@code null}. * @see #name(String) */ public final Cache2kBuilder name(String uniqueName, Class clazz, String fieldName) { if (fieldName == null) { throw new NullPointerException(); } if (uniqueName == null) { return name(clazz, fieldName); } cfg().setName(uniqueName + '~' + clazz.getName() + "." + fieldName); return this; } /** * Constructs a cache name out of the class name and field name. Result example: * {@code com.example.ImagePool.id2Image} * *

See {@link #name(String)} for a general discussion about cache names. * * @see #name(String) */ public final Cache2kBuilder name(Class clazz, String fieldName) { if (fieldName == null) { throw new NullPointerException(); } cfg().setName(clazz.getName() + "." + fieldName); return this; } /** * Sets a cache name from the fully qualified class name. * *

See {@link #name(String)} for a general discussion about cache names. * * @see #name(String) */ public final Cache2kBuilder name(Class clazz) { cfg().setName(clazz.getName()); return this; } /** * Sets the name of a cache. If a name is specified it must be ensured it is unique within * the cache manager. Cache names are used at several places to have a unique ID of a cache. * For example, for referencing additional configuration or to register JMX beans. * *

If a name is not specified the cache generates a name automatically. The name is * inferred from the call stack trace and contains the simple class name, the method and * the line number of the of the caller to {@code build()}. The name also contains * a random number. Automatically generated names don't allow reliable management, logging and * additional configuration of caches. If no name is set, {@link #build()} will always create * a new cache with a new unique name within the cache manager. Automatically generated * cache names start with the character {@code '_'} as prefix to separate the names from the * usual class name space. * *

For maximum compatibility cache names should only be composed with the characters * {@code [-_.a-zA-Z0-9]}. The characters {@code {}|\^&=";:<>*?/} are not allowed in a cache name. * The reason for restricting the characters in names, is that the names may be used to derive * other resource names from it, e.g. for file based storage. The characters {@code *} and * {@code ?} are used for wildcards in JMX and cannot be used in an object name. * *

The method is overloaded with variants to provide a naming convention of names. * *

For brevity within log messages and other displays the cache name may be * shortened if the manager name is included as prefix. * * @see Cache#getName() */ public final Cache2kBuilder name(String v) { cfg().setName(v); return this; } /** * Expired data is kept in the cache until the entry is evicted. This consumes memory, * but if the data is accessed again the previous data can be used by the cache loader * for optimizing (e.g. if-modified-since for a HTTP request). Default value: {@code false} * * @see AdvancedCacheLoader */ public final Cache2kBuilder keepDataAfterExpired(boolean v) { cfg().setKeepDataAfterExpired(v); return this; } /** * The maximum number of entries hold by the cache. When the maximum size is reached, by * inserting new entries, the cache eviction algorithm will remove one or more entries * to keep the size within the configured limit. * *

The value {@code Long.MAX_VALUE} means the capacity is not limited. * *

The default value is {@link Cache2kConfig#DEFAULT_ENTRY_CAPACITY}. The odd value * is intentional, to serve as an indicate for SREs that the cache is running on its default * size. A low capacity default is different to caches like Guava or Caffeine, that create * an unbounded cache by default, which potentially a memory leak. */ public final Cache2kBuilder entryCapacity(long v) { cfg().setEntryCapacity(v); return this; } /** * When set to {@code true}, cached values do not expire by time. Entries will need to be removed * from the cache explicitly or will be evicted if capacity constraints are reached. * *

Setting eternal to {@code false} signals that the data should expire, but there is no * predefined expiry value at programmatic level. This value needs to be set by other * means, e.g. within a configuration file. * *

The default behavior of the cache is identical to the setting of eternal. Entries will * not expire. When eternal was set explicitly it cannot be reset to another value afterwards. * This should protect against misconfiguration. * * @throws IllegalArgumentException in case a previous setting is reset */ public final Cache2kBuilder eternal(boolean v) { cfg().setEternal(v); return this; } /** * Time duration after insert or updated an cache entry expires. * To switch off time based expiry use {@link #eternal(boolean)}. The expiry * happens via a timer event and may lag approximately one second by default, see * {@link #timerLag(long, TimeUnit)}. For exact expiry specify an * {@link ExpiryPolicy} and enable {@link #sharpExpiry(boolean)}. * *

If an {@link ExpiryPolicy} is specified in combination to this value, * the maximum expiry duration is capped to the value specified here. * *

A value of {@code 0} or {@link org.cache2k.expiry.ExpiryTimeValues#NOW} means * every entry should expire immediately. This can be useful to disable caching via * configuration. * *

A value of {@code Long.MAX_VALUE} milliseconds or more is treated as * eternal expiry. * * @throws IllegalArgumentException if {@link #eternal(boolean)} was set to true * @see * cache2k user guide - Expiry and Refresh */ public final Cache2kBuilder expireAfterWrite(long v, TimeUnit u) { cfg().setExpireAfterWrite(toDuration(v, u)); return this; } /** * Change the maximum lag time for timer events. Timer events are used for * expiry and refresh operations. The default is approximately one second. */ public final Cache2kBuilder timerLag(long v, TimeUnit u) { cfg().setTimerLag(toDuration(v, u)); return this; } private static Duration toDuration(long v, TimeUnit u) { return Duration.ofMillis(u.toMillis(v)); } /** * Sets customization for propagating loader exceptions. By default loader exceptions * are wrapped into a {@link CacheLoaderException}. */ public final Cache2kBuilder exceptionPropagator( ExceptionPropagator ep) { cfg().setExceptionPropagator(wrapCustomizationInstance(ep)); return this; } /** Wraps to factory but passes on nulls. */ private static CustomizationReferenceSupplier wrapCustomizationInstance(T obj) { return new CustomizationReferenceSupplier(obj); } /** * Enables read through operation and sets a cache loader. Different loader types * are available: {@link CacheLoader}, {@link AdvancedCacheLoader}. * * @see CacheLoader for general discussion on cache loaders */ public final Cache2kBuilder loader(CacheLoader l) { cfg().setLoader(wrapCustomizationInstance(l)); return this; } /** * Enables read through operation and sets a cache loader. Different loader types * are available: {@link CacheLoader}, {@link AdvancedCacheLoader}. * * @see CacheLoader for general discussion on cache loaders */ public final Cache2kBuilder loader(AdvancedCacheLoader l) { cfg().setAdvancedLoader(wrapCustomizationInstance(l)); return this; } /** * Enables read through operation and sets a cache loader. Different loader types * are available: {@link CacheLoader}, {@link AdvancedCacheLoader}, * {@link AsyncCacheLoader} * * @see CacheLoader for general discussion on cache loaders */ public final Cache2kBuilder loader(AsyncCacheLoader l) { cfg().setAsyncLoader(wrapCustomizationInstance(l)); return this; } public final Cache2kBuilder bulkLoader(AsyncBulkCacheLoader l) { loader(l); return this; } public final Cache2kBuilder bulkLoader(BulkCacheLoader l) { loader(l); return this; } /** * Enables write through operation and sets a writer customization that gets * called synchronously upon cache mutations. By default write through is not enabled. */ public final Cache2kBuilder writer(CacheWriter w) { cfg().setWriter(wrapCustomizationInstance(w)); return this; } /** * Listener that is called after a cache is closed. This is mainly used for the JCache * integration. */ public final Cache2kBuilder addCacheClosedListener(CacheClosedListener listener) { cfg().getLifecycleListeners().add(wrapCustomizationInstance(listener)); return this; } /** * Add a listener. The listeners will be executed in a synchronous mode, meaning, * further processing for an entry will stall until a registered listener is executed. * The expiry will be always executed asynchronously. * * @throws IllegalArgumentException if an identical listener is already added. * @param listener The listener to add */ public final Cache2kBuilder addListener(CacheEntryOperationListener listener) { cfg().getListeners().add(wrapCustomizationInstance(listener)); return this; } /** * A set of listeners. Listeners added in this collection will be * executed in a asynchronous mode. * * @throws IllegalArgumentException if an identical listener is already added. * @param listener The listener to add */ public final Cache2kBuilder addAsyncListener(CacheEntryOperationListener listener) { cfg().getAsyncListeners().add(wrapCustomizationInstance(listener)); return this; } /** * Set expiry policy to use. * *

If this is specified the maximum expiry time is still limited to the value in * {@link #expireAfterWrite}. If {@link #expireAfterWrite(long, java.util.concurrent.TimeUnit)} * is set to 0 then expiry calculation is not used, all entries expire immediately. */ public final Cache2kBuilder expiryPolicy(ExpiryPolicy c) { cfg().setExpiryPolicy(wrapCustomizationInstance(c)); return this; } /** * When {@code true}, enable background refresh / refresh ahead. After the expiry time of a * value is reached, the loader is invoked to fetch a fresh value. The old value will be * returned by the cache, although it is expired, and will be replaced by the new value, * once the loader is finished. In the case there are not enough loader threads available, * the value will expire immediately and the next {@code get()} request will trigger the load. * *

Once refreshed, the entry is in a probation period. If it is not accessed until the next * expiry, no refresh will be done and the entry expires regularly. This means that the * time an entry stays within the probation period is determined by the configured expiry time * or the {@code ExpiryPolicy}. In case an entry is not accessed any more it needs to * reach the expiry time twice before being removed from the cache. * *

The number of threads used to do the refresh are configured via * {@link #loaderThreadCount(int)} * *

By default, refresh ahead is not enabled. * * @see CacheLoader * @see #loaderThreadCount(int) */ public final Cache2kBuilder refreshAhead(boolean f) { cfg().setRefreshAhead(f); return this; } /** * By default the expiry time is not exact, which means, a value might be visible for up to * a second longer after the requested time of expiry. The time lag depends on the system load * and the parameter {@link #timerLag(long, TimeUnit)} * Switching to {@code true}, means that values will not be visible when the time is reached that * {@link ExpiryPolicy} returned. This has no effect on {@link #expireAfterWrite(long, TimeUnit)}. */ public final Cache2kBuilder sharpExpiry(boolean f) { cfg().setSharpExpiry(f); return this; } /** * If no separate executor is set via {@link #loaderExecutor(Executor)} the cache will * create a separate thread pool used exclusively by it. Defines the maximum number of threads * this cache should use for calls to the {@link CacheLoader}. The default is one thread * per available CPU. If threads are exhausted the executor rejects the execution. If that * happens the cache will carry out load requests in the calling thread or, in case of a refresh, * drop the request. * *

If a separate executor is defined the parameter has no effect. * * @see #loaderExecutor(Executor) * @see #refreshExecutor(Executor) */ public final Cache2kBuilder loaderThreadCount(int v) { cfg().setLoaderThreadCount(v); return this; } /** * Ensure that the cache value is stored via direct object reference and that * no serialization takes place. Cache clients leveraging the fact that an in heap * cache stores object references directly should set this value. * *

If this value is not set to true this means: The key and value objects need to have a * defined serialization mechanism and the cache may choose to transfer off the heap. * For cache2k version 1.0 this value has no effect. It should be * used by application developers to future proof the applications with upcoming versions. */ public final Cache2kBuilder storeByReference(boolean v) { cfg().setStoreByReference(v); return this; } /** * Sets a custom resilience policy to control the cache behavior in the presence * of exceptions from the loader. A specified policy will be ignored if * {@link #expireAfterWrite} is set to 0. */ public final Cache2kBuilder resiliencePolicy(ResiliencePolicy v) { cfg().setResiliencePolicy(wrapCustomizationInstance(v)); return this; } public final Cache2kBuilder resiliencePolicy( CustomizationSupplier> v) { cfg().setResiliencePolicy(v); return this; } /** * To increase performance cache2k optimizes the eviction and does eviction in * greater chunks. With strict eviction, the eviction is done for one entry * as soon as the capacity constraint is met. This is primarily used for * testing and evaluation purposes. */ public final Cache2kBuilder strictEviction(boolean flag) { cfg().setStrictEviction(flag); return this; } /** * When {@code true}, {@code null} values are allowed in the cache. In the default configuration * {@code null} values are prohibited. * *

See the chapter in the user guide for details on {@code null} values. * *

When used within Spring, {@code null} are allowed by default. * * @see CacheLoader#load(Object) * @see ExpiryPolicy#calculateExpiryTime(Object, Object, long, CacheEntry) */ public final Cache2kBuilder permitNullValues(boolean flag) { cfg().setPermitNullValues(flag); return this; } /** * By default statistic gathering is enabled. Switching this to {@code true} will disable all * statistics that have significant overhead. Whether the values become visible in monitoring * can be controlled via {@link #disableMonitoring(boolean)} */ public final Cache2kBuilder disableStatistics(boolean flag) { cfg().setDisableStatistics(flag); return this; } /** * Enables that time of an refresh (means update or freshness check of a value) is * available at {@link MutableCacheEntry#getModificationTime()}. * * @see MutableCacheEntry#getModificationTime() */ public final Cache2kBuilder recordModificationTime(boolean flag) { cfg().setRecordModificationTime(flag); return this; } /** * When {@code true}, optimize for high core counts and applications that do lots of mutations * in the cache. When switched on, the cache will occupy slightly more memory and eviction * efficiency may drop slightly. This overhead is negligible for big cache sizes (100K and more). * *

Typical interactive do not need to enable this. May improve concurrency for applications * that utilize all cores and cache operations account for most CPU cycles. */ public final Cache2kBuilder boostConcurrency(boolean f) { cfg().setBoostConcurrency(f); return this; } /** * Disables reporting of cache metrics to monitoring systems or management. * This should be set, e.g. if a cache is created dynamically and * intended to be short lived. All extensions for monitoring or management * respect this parameter. */ public final Cache2kBuilder disableMonitoring(boolean f) { cfg().setDisableMonitoring(f); return this; } /** * Thread pool / executor service to use for triggered load operations. If no executor is * specified the cache will create a thread pool, if needed. * *

The loader thread pool is used by the cache for executing load requests concurrent * to the application, when a {@link Cache#loadAll(Iterable)} is issued. If no bulk loader * is specified the thread pool will be used to carry out load requests in parallel. If an * {@link AsyncCacheLoader} is used, the cache itself does not use the loader executor. * *

The executor should reject when not enough threads are available. * In that case the cache will use the calling thread for the load operation. * * @see #loaderThreadCount(int) */ public final Cache2kBuilder loaderExecutor(Executor v) { cfg().setLoaderExecutor(new CustomizationReferenceSupplier(v)); return this; } /** * Thread pool / executor service to use for refresh ahead operations. If not * specified the same refresh ahead operation will use the thread pool defined by * {@link #loaderExecutor(Executor)} or a cache local pool is created. * *

The executor for refresh operations may reject execution when not enough resources * are available. If a refresh is rejected, the cache entry expires normally. * * @see #loaderThreadCount(int) * @see #loaderExecutor(Executor) */ public final Cache2kBuilder refreshExecutor(Executor v) { cfg().setRefreshExecutor(new CustomizationReferenceSupplier(v)); return this; } /** * Executor for asynchronous operations and expiry. The {@link ForkJoinPool#commonPool()} is * used by default. */ public final Cache2kBuilder executor(Executor v) { cfg().setExecutor(new CustomizationReferenceSupplier(v)); return this; } /** * Use a different scheduler to run timer tasks for. */ public final Cache2kBuilder scheduler(Scheduler v) { cfg().setScheduler(new CustomizationReferenceSupplier(v)); return this; } /** * Use a different time reference. */ public final Cache2kBuilder timeReference(TimeReference v) { cfg().setTimeReference(new CustomizationReferenceSupplier(v)); return this; } /** * Executor for asynchronous listeners. If not configured the common * asynchronous executor is used as defined by {@link #executor(Executor)} * * @see #addAsyncListener(CacheEntryOperationListener) */ public final Cache2kBuilder asyncListenerExecutor(Executor v) { cfg().setAsyncListenerExecutor(new CustomizationReferenceSupplier(v)); return this; } /** * Set the weigher to be used to calculate the entry weight. The parameter * {@link #maximumWeight(long)} needs to be specified as well. Using a weigher has a slightly * performance impact on the update of existing entries. When a weigher is set the * {@link #entryCapacity(long)} parameter is ignored. */ public final Cache2kBuilder weigher(Weigher v) { cfg().setWeigher(new CustomizationReferenceSupplier>(v)); return this; } /** * Specifies the maximum weight of entries the cache may contain. To obtain the entry weight a * {@link Weigher} must be specified via {@link #weigher}. *

* The weight of an entry does not influence which entry is evicted next, but is only used to * constrain the capacity of the cache. The cache implementation tries the best to keep the cache * within its maximum weight limit, but eviction may kick in before or after reaching the limit. *

* The maximum weight setting cannot be used together with {@link #entryCapacity(long)}. */ public final Cache2kBuilder maximumWeight(long v) { cfg().setMaximumWeight(v); return this; } /** * Call the consumer with this builder. This can be used to apply configuration * fragments within the fluent configuration scheme. */ public final Cache2kBuilder setup(Consumer> consumer) { consumer.accept(this); return this; } /** Enable a feature */ public final Cache2kBuilder enable(Class feature) { ToggleFeature.enable(this, feature); return this; } public final Cache2kBuilder disable(Class feature) { ToggleFeature.disable(this, feature); return this; } /** * Configure a config section. If the section is not existing it a new * section is created. If the section is existing the existing instance * is modified. * * @param configSectionClass type of the config section that is created or altered * @param builderAction lambda that alters the config section via its builder * @param type of the builder for the config section * @param the type of the config section */ public final , CFG extends ConfigSection> Cache2kBuilder with(Class configSectionClass, Consumer builderAction) { CFG section = cfg().getSections().getSection(configSectionClass); if (section == null) { try { section = configSectionClass.getConstructor().newInstance(); } catch (Exception e) { throw new Error("config bean needs working default constructor", e); } cfg().getSections().add(section); } builderAction.accept(section.builder()); return this; } /** * Execute on the underlying configuration object. This can be used to * set customization suppliers, like {@link Cache2kConfig#setExecutor(CustomizationSupplier)} * instead of instances. */ public Cache2kBuilder set(Consumer> configAction) { configAction.accept(config()); return this; } /** * Execute setup code for a feature or customization and configure * its associated configuration section via its builder. * * @param setupAction function modifying the configuration * @param builderAction function for configuring the customization * @param the builder for the customizations' configuration section * @param the configuration section * @param the supplier for the customization */ public , CFG extends ConfigSection, SUP extends WithSection & CustomizationSupplier> Cache2kBuilder setupWith( Function, SUP> setupAction, Consumer builderAction) { with(setupAction.apply(this).getConfigClass(), builderAction); return this; } /** * Executes setup code for a feature or customization which has additional parameters * and configures it via its builder. * * @param enabler setup function returning am associated configuration * @param builderAction function to configure */ public , CFG extends ConfigBean> Cache2kBuilder setup(Function, CFG> enabler, Consumer builderAction) { builderAction.accept(enabler.apply(this).builder()); return this; } /** * Enables a toggle feature which has additional parameters and configures it via its builder. * * @param featureType Type of feature which has additional bean properties * @param builderAction function to configure the feature */ public , T extends ToggleFeature & ConfigBean> Cache2kBuilder enable(Class featureType, Consumer builderAction) { T bean = ToggleFeature.enable(this, featureType); builderAction.accept(bean.builder()); return this; } /** * Enables a feature and configures its associated configuration section via its builder. * Be aware that a section might be existing and preconfigured already, the semantics * are identical to {@link #with(Class, Consumer)} */ public , T extends ToggleFeature & WithSection, CFG extends ConfigSection> Cache2kBuilder enableWith( Class featureType, Consumer builderAction) { T bean = ToggleFeature.enable(this, featureType); with(bean.getConfigClass(), builderAction); return this; } /** * Returns the configuration object this builder operates on. Changes to the configuration also * will influence the created cache when {@link #build()} is called. The method does not * return the effective configuration if additional external/XML configuration is present, since * this is applied when {@code build} is called. On the other hand, the method can be used * to inspect the effective configuration after {@code build} completed. * * @return configuration objects with the parameters set in the builder. */ @Override public final Cache2kConfig config() { return cfg(); } /** * Get the associated cache manager. */ public final CacheManager getManager() { if (manager == null) { manager = CacheManager.getInstance(); } return manager; } /** * Builds a cache with the specified configuration parameters. * *

If XML configuration is present, the section for the cache name is looked up and * the configuration in it applied, before the cache is build. * * @throws IllegalArgumentException if a cache of the same name is already active in the * cache manager * @throws IllegalArgumentException if a configuration entry for the named cache is required but * not present */ public final Cache build() { return CacheManager.PROVIDER.createCache(getManager(), cfg()); } }