001package org.cache2k;
002
003/*
004 * #%L
005 * cache2k API only package
006 * %%
007 * Copyright (C) 2000 - 2016 headissue GmbH, Munich
008 * %%
009 * This program is free software: you can redistribute it and/or modify
010 * it under the terms of the GNU General Public License as
011 * published by the Free Software Foundation, either version 3 of the 
012 * License, or (at your option) any later version.
013 * 
014 * This program is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017 * GNU General Public License for more details.
018 * 
019 * You should have received a copy of the GNU General Public 
020 * License along with this program.  If not, see
021 * <http://www.gnu.org/licenses/gpl-3.0.html>.
022 * #L%
023 */
024
025import org.cache2k.spi.Cache2kCoreProvider;
026import org.cache2k.spi.SingleProviderResolver;
027
028import java.util.Collection;
029import java.util.concurrent.TimeUnit;
030
031/**
032 * @author Jens Wilke; created: 2013-06-25
033 */
034public abstract class CacheBuilder<K,T>
035  extends RootAnyBuilder<K, T> implements Cloneable {
036
037  private static CacheBuilder PROTOTYPE;
038
039  static {
040    try {
041      Cache2kCoreProvider _provider =
042        SingleProviderResolver.getInstance().resolve(Cache2kCoreProvider.class);
043      PROTOTYPE = _provider.getBuilderImplementation().newInstance();
044    } catch (Exception ex) {
045      throw new Error("cache2k-core module missing, no builder prototype", ex);
046    }
047  }
048
049  @SuppressWarnings("unchecked")
050  public static <K,T> CacheBuilder<K,T> newCache(Class<K> _keyType, Class<T> _valueType) {
051    CacheBuilder<K,T> cb = null;
052    try {
053      cb = (CacheBuilder<K,T>) PROTOTYPE.clone();
054    } catch (CloneNotSupportedException ignored) {  }
055    cb.ctor(_keyType, _valueType, null);
056    return cb;
057  }
058
059  @SuppressWarnings("unchecked")
060  public static <K, C extends Collection<T>, T> CacheBuilder<K, C> newCache(
061    Class<K> _keyType, Class<C> _collectionType, Class<T> _entryType) {
062    CacheBuilder<K,C> cb = null;
063    try {
064      cb = (CacheBuilder<K,C>) PROTOTYPE.clone();
065    } catch (CloneNotSupportedException ignored) { }
066    cb.ctor(_keyType, _collectionType, _entryType);
067    return cb;
068  }
069
070  protected EntryExpiryCalculator entryExpiryCalculator;
071  protected CacheSource cacheSource;
072  protected CacheSourceWithMetaInfo cacheSourceWithMetaInfo;
073  protected RefreshController refreshController;
074  protected ExperimentalBulkCacheSource experimentalBulkCacheSource;
075  protected BulkCacheSource bulkCacheSource;
076  protected ExceptionExpiryCalculator exceptionExpiryCalculator;
077
078  /** Builder is constructed from prototype */
079  protected void ctor(Class<K> _keyType, Class<T> _valueType, Class<?> _entryType) {
080    root = this;
081    config = new CacheConfig();
082    config.setValueType(_valueType);
083    config.setKeyType(_keyType);
084    config.setEntryType(_entryType);
085  }
086
087  /**
088   * Constructs a cache name out of the simple class name and fieldname.
089   *
090   * a cache name should be unique within an application / cache manager!
091   */
092  public CacheBuilder<K, T> name(Class<?> _class, String _fieldName) {
093    config.setName(_class.getSimpleName() + "." + _fieldName);
094    return this;
095  }
096
097  public CacheBuilder<K, T> name(Class<?> _class) {
098    config.setName(_class.getSimpleName());
099    return this;
100  }
101
102  /**
103   * Constructs a cache name out of the simple class name and fieldname.
104   *
105   * a cache name should be unique within an application / cache manager!
106   */
107  public CacheBuilder<K, T> name(Object _containingObject, String _fieldName) {
108    return name(_containingObject.getClass(), _fieldName);
109  }
110
111  public CacheBuilder<K, T> name(String v) {
112    config.setName(v);
113    return this;
114  }
115
116  public CacheBuilder<K, T> keepDataAfterExpired(boolean v) {
117    config.setKeepDataAfterExpired(v);
118    return this;
119  }
120
121  public CacheBuilder<K, T> maxSize(int v) {
122    config.setMaxSize(v);
123    return this;
124  }
125
126  public CacheBuilder<K, T> maxSizeBound(int v) {
127    config.setMaxSizeHighBound(v);
128    return this;
129  }
130
131  /**
132   * Keep entries forever. Default is false. By default the cache uses an expiry time
133   * of 10 minutes.
134   */
135  public CacheBuilder<K, T> eternal(boolean v) {
136    config.setEternal(v);
137    return this;
138  }
139
140  /**
141   * If an exceptions gets thrown by the cache source, suppress it if there is
142   * a previous value. When this is active, and an exception was suppressed
143   * the expiry is determined by the exception expiry settings. Default: true
144   */
145  public CacheBuilder<K, T> suppressExceptions(boolean v) {
146    config.setSuppressExceptions(v);
147    return this;
148  }
149
150  public CacheBuilder<K, T> heapEntryCapacity(int v) {
151    config.setHeapEntryCapacity(v);
152    return this;
153  }
154
155  /**
156   * Set the time duration after an entry expires. To switch off time
157   * based expiry use {@link #eternal(boolean)}. A value of 0 effectively
158   * disables the cache.
159   *
160   * <p/>If an {@link org.cache2k.EntryExpiryCalculator} is set, this setting
161   * controls the maximum possible expiry duration.
162   */
163  public CacheBuilder<K, T> expiryDuration(long v, TimeUnit u) {
164    config.setExpiryMillis(u.toMillis(v));
165    return this;
166  }
167
168  /**
169   * Separate timeout in the case an exception was thrown in the cache source.
170   * By default 10% of the normal expiry is used.
171   */
172  public CacheBuilder<K, T> exceptionExpiryDuration(long v, TimeUnit u) {
173    config.setExceptionExpiryMillis(u.toMillis(v));
174    return this;
175  }
176
177  /**
178   * @deprecated since 0.20, please use {@link #expiryDuration}
179   */
180  public CacheBuilder<K, T> expirySecs(int v) {
181    config.setExpiryMillis(v * 1000);
182    return this;
183  }
184
185  /**
186   * @deprecated since 0.20, please use {@link #expiryDuration}
187   */
188  public CacheBuilder<K, T> expiryMillis(long v) {
189    config.setExpiryMillis(v);
190    return this;
191  }
192
193  public CacheBuilder<K, T> source(CacheSource<K, T> g) {
194    cacheSource = g;
195    return this;
196  }
197
198  public CacheBuilder<K, T> source(CacheSourceWithMetaInfo<K, T> g) {
199    cacheSourceWithMetaInfo = g;
200    return this;
201  }
202
203  public CacheBuilder<K, T> source(ExperimentalBulkCacheSource<K, T> g) {
204    experimentalBulkCacheSource = g;
205    return this;
206  }
207
208  public CacheBuilder<K, T> source(BulkCacheSource<K, T> g) {
209    bulkCacheSource = g;
210    return this;
211  }
212
213  /**
214   * Set expiry calculator to use. If {@link #expiryDuration(long, java.util.concurrent.TimeUnit)}
215   * is set to 0 then expiry calculation is not used, all entries expire immediately.
216   */
217  public CacheBuilder<K, T> entryExpiryCalculator(EntryExpiryCalculator c) {
218    entryExpiryCalculator = c;
219    return this;
220  }
221
222  /**
223   * Set expiry calculator to use in case of an exception happened in the {@link CacheSource}.
224   */
225  public CacheBuilder<K, T> exceptionExpiryCalculator(ExceptionExpiryCalculator c) {
226    exceptionExpiryCalculator = c;
227    return this;
228  }
229
230  /**
231   * @deprecated since 0.20, please use {@link #entryExpiryCalculator}
232   */
233  public CacheBuilder<K, T> refreshController(RefreshController c) {
234    refreshController = c;
235    return this;
236  }
237
238  public CacheBuilder<K, T> implementation(Class<?> c) {
239    config.setImplementation(c);
240    return this;
241  }
242
243  @Deprecated
244  public CacheConfig getConfig() {
245    return null;
246  }
247
248
249  /**
250   * Builds a cache with the specified configuration parameters.
251   * The builder reused to build caches with similar or identical
252   * configuration. The builder is not thread safe.
253   */
254  public abstract Cache<K, T> build();
255
256}