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