/*
* Copyright Terracotta, Inc.
*
* 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.
*/
package org.ehcache.expiry;
import org.ehcache.ValueSupplier;
/**
* Utility class for getting predefined {@link Expiry} instances.
*/
public final class Expirations {
/**
* Get an {@link Expiry} instance for a non expiring (ie. "eternal") cache.
*
* @return the no expiry instance
*/
public static Expiry<Object, Object> noExpiration() {
return NoExpiry.INSTANCE;
}
/**
* Get a time-to-live (TTL) {@link Expiry} instance for the given {@link Duration}.
*
* @param timeToLive the TTL duration
* @return a TTL expiry
*/
public static Expiry<Object, Object> timeToLiveExpiration(Duration timeToLive) {
if (timeToLive == null) {
throw new NullPointerException("Duration cannot be null");
}
return new TimeToLiveExpiry(timeToLive);
}
/**
* Get a time-to-idle (TTI) {@link Expiry} instance for the given {@link Duration}.
*
* @param timeToIdle the TTI duration
* @return a TTI expiry
*/
public static Expiry<Object, Object> timeToIdleExpiration(Duration timeToIdle) {
if (timeToIdle == null) {
throw new NullPointerException("Duration cannot be null");
}
return new TimeToIdleExpiry(timeToIdle);
}
/**
* Fluent API for creating an Expiry instance where you can specify constant values for creation, access and update time.
* Unspecified values will be set to {@code Duration.INFINITE} for create and {@code null} for access and update, matching
* the {@link #noExpiration() no expiration} expiry.
*
* @param <K> the key type for the cache
* @param <V> the value type for the cache
* @return an {@link Expiry} builder
*/
public static <K, V> ExpiryBuilder<K, V> builder() {
return new ExpiryBuilder<K, V>();
}
private Expirations() {
//
}
/**
* Simple implementation of the {@link Expiry} interface allowing to set constants to each expiry types.
*/
private static class BaseExpiry<K, V> implements Expiry<K, V> {
private final Duration create;
private final Duration access;
private final Duration update;
BaseExpiry(Duration create, Duration access, Duration update) {
this.create = create;
this.access = access;
this.update = update;
}
@Override
public Duration getExpiryForCreation(K key, V value) {
return create;
}
@Override
public Duration getExpiryForAccess(K key, ValueSupplier<? extends V> value) {
return access;
}
@Override
public Duration getExpiryForUpdate(K key, ValueSupplier<? extends V> oldValue, V newValue) {
return update;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final BaseExpiry that = (BaseExpiry)o;
if (access != null ? !access.equals(that.access) : that.access != null) return false;
if (create != null ? !create.equals(that.create) : that.create != null) return false;
if (update != null ? !update.equals(that.update) : that.update != null) return false;
return true;
}
@Override
public int hashCode() {
int result = create != null ? create.hashCode() : 0;
result = 31 * result + (access != null ? access.hashCode() : 0);
result = 31 * result + (update != null ? update.hashCode() : 0);
return result;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "{" +
"create=" + create +
", access=" + access +
", update=" + update +
'}';
}
}
private static class TimeToLiveExpiry extends BaseExpiry<Object, Object> {
TimeToLiveExpiry(Duration ttl) {
super(ttl, null, ttl);
}
}
private static class TimeToIdleExpiry extends BaseExpiry<Object, Object> {
TimeToIdleExpiry(Duration tti) {
super(tti, tti, tti);
}
}
private static class NoExpiry extends BaseExpiry<Object, Object> {
private static final Expiry<Object, Object> INSTANCE = new NoExpiry();
private NoExpiry() {
super(Duration.INFINITE, null, null);
}
}
/**
* Builder to create a simple {@link Expiry}.
*
* @param <K> Key type of the cache entries
* @param <V> Value type of the cache entries
*/
public static final class ExpiryBuilder<K, V> {
private Duration create = Duration.INFINITE;
private Duration access = null;
private Duration update = null;
private ExpiryBuilder() {}
/**
* Set TTL since creation
*
* @param create TTL since creation
* @return this builder
*/
public ExpiryBuilder<K, V> setCreate(Duration create) {
this.create = create;
return this;
}
/**
* Set TTL since last access
*
* @param access TTL since last access
* @return this builder
*/
public ExpiryBuilder<K, V> setAccess(Duration access) {
this.access = access;
return this;
}
/**
* Set TTL since last update
*
* @param update TTL since last update
* @return this builder
*/
public ExpiryBuilder<K, V> setUpdate(Duration update) {
this.update = update;
return this;
}
/**
*
* @return an {@link Expiry}
*/
public Expiry<K, V> build() {
return new BaseExpiry<K, V>(create, access, update);
}
}
}