/*
 * 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.
   *
   * @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;
    }

    public Expiry<K, V> build() {
      return new BaseExpiry<K, V>(create, access, update);
    }
  }
}

@@ -2099,24 +2099,112 @@
 xpiry.%0A   *%0A
+   * @param %3CK%3E the key type for the cache%0A   * @param %3CV%3E the value type for the cache%0A
    * @return
@@ -5808,24 +5808,80 @@
 his;%0A    %7D%0A%0A
+    /**%0A     *%0A     * @return an %7B@link Expiry%7D%0A     */%0A
     public E

Add proper javadoc