javax.cache.expiry.Duration Maven / Gradle / Ivy
/**
* Copyright 2011-2016 Terracotta, Inc.
* Copyright 2011-2016 Oracle America Incorporated
*
* 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 javax.cache.expiry;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
/**
* A {@link java.io.Serializable} duration of time.
*
* Although this class is not declared final, it is not intended for extension. The behavior
* is undefined when subclasses are created and used.
*
* @author Yannis Cosmadopoulos
* @author Greg Luck
* @author Brian Oliver
* @since 1.0
* @see ExpiryPolicy
*/
public class Duration implements Serializable {
/**
* The serialVersionUID required for {@link java.io.Serializable}.
*/
public static final long serialVersionUID = 201305101442L;
/**
* ETERNAL (forever).
*/
public static final Duration ETERNAL = new Duration();
/**
* One day.
*/
public static final Duration ONE_DAY = new Duration(DAYS, 1);
/**
* One hour.
*/
public static final Duration ONE_HOUR = new Duration(HOURS, 1);
/**
* Thirty minutes.
*/
public static final Duration THIRTY_MINUTES = new Duration(MINUTES, 30);
/**
* Twenty minutes.
*/
public static final Duration TWENTY_MINUTES = new Duration(MINUTES, 20);
/**
* Ten minutes.
*/
public static final Duration TEN_MINUTES = new Duration(MINUTES, 10);
/**
* Five minutes.
*/
public static final Duration FIVE_MINUTES = new Duration(MINUTES, 5);
/**
* One minute.
*/
public static final Duration ONE_MINUTE = new Duration(MINUTES, 1);
/**
* Zero (no time).
*/
public static final Duration ZERO = new Duration(SECONDS, 0);
/**
* The unit of time to specify time in. The minimum time unit is milliseconds.
*/
private final TimeUnit timeUnit;
/**
* How long, in the specified units, the cache entries should live.
* The lifetime is measured from the cache entry was last accessed or
* mutated.
*/
private final long durationAmount;
/**
* Constructs an eternal duration ({@link #isEternal} is true). Since the duration is immutable
* the constant {@link #ETERNAL} should be used alternatively.
*/
public Duration() {
this.timeUnit = null;
this.durationAmount = 0;
}
/**
* Constructs a duration. The eternal duration ({@link #isEternal} is true) is represented by
* specifying {@code null} for {@code timeUnit} and {@code 0} for {@code durationAmount}.
*
* @param timeUnit the unit of time to specify time in. The minimum time unit is milliseconds.
* @param durationAmount how long, in the specified units, the cache entries should live.
* @throws NullPointerException if timeUnit is null and the {@code durationAmount} is not 0
* @throws IllegalArgumentException if durationAmount is less than 0 or a TimeUnit less than milliseconds is specified
*/
public Duration(TimeUnit timeUnit, long durationAmount) {
if (timeUnit == null) {
if (durationAmount == 0) {
//allow creation of an Eternal Duration
this.timeUnit = null;
this.durationAmount = 0;
} else {
throw new NullPointerException();
}
} else {
switch (timeUnit) {
case NANOSECONDS:
case MICROSECONDS:
throw new IllegalArgumentException("Must specify a TimeUnit of milliseconds or higher.");
default:
this.timeUnit = timeUnit;
break;
}
if (durationAmount < 0) {
throw new IllegalArgumentException("Cannot specify a negative durationAmount.");
}
this.durationAmount = durationAmount;
}
}
/**
* Constructs a {@link Duration} based on the duration between two
* specified points in time (since the Epoc), measured in milliseconds.
*
*
If either parameter is {@code Long.MAX_VALUE} an eternal duration ({@link #isEternal}
* is true) will be constructed.
*
* @param startTime the start time (since the Epoc)
* @param endTime the end time (since the Epoc)
*/
public Duration(long startTime, long endTime) {
if (startTime == Long.MAX_VALUE || endTime == Long.MAX_VALUE) {
//we're dealing with arithmetic involving an ETERNAL value
//so the result must be ETERNAL
timeUnit = null;
durationAmount = 0;
} else if (startTime < 0) {
throw new IllegalArgumentException("Cannot specify a negative startTime.");
} else if (endTime < 0) {
throw new IllegalArgumentException("Cannot specify a negative endTime.");
} else {
timeUnit = TimeUnit.MILLISECONDS;
durationAmount = Math.max(startTime, endTime) - Math.min(startTime, endTime);
}
}
/**
* Obtain the TimeUnit for the Duration
*
* @return the TimeUnit
*/
public TimeUnit getTimeUnit() {
return timeUnit;
}
/**
* Obtain the number of TimeUnits in the Duration
*
* @return the number of TimeUnits
*/
public long getDurationAmount() {
return durationAmount;
}
/**
* Determines if a {@link Duration} is eternal (forever).
*
* @return true if the {@link Duration} is eternal
*/
public boolean isEternal() {
return timeUnit == null && durationAmount == 0;
}
/**
* Determines if a {@link Duration} is zero.
*
* @return true if the {@link Duration} is zero
*/
public boolean isZero() {
return timeUnit != null && durationAmount == 0;
}
/**
* Calculates the adjusted time (represented in milliseconds from the Epoc)
* given a specified time in milliseconds (to be adjusted) by the duration.
*
*
If this instance represents an eternal duration ({@link #isEternal}
* is true), the value {@code Long.MAX_VALUE} is returned.
*
* @param time the time from which to adjust given the duration
* @return the adjusted time
*/
public long getAdjustedTime(long time) {
if (isEternal()) {
return Long.MAX_VALUE;
} else {
return time + timeUnit.toMillis(durationAmount);
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
} else if (other == null || getClass() != other.getClass()) {
return false;
} else {
Duration duration = (Duration) other;
if (this.timeUnit == null && duration.timeUnit == null &&
this.durationAmount == duration.durationAmount) {
return true;
} else if (this.timeUnit != null && duration.timeUnit != null) {
long time1 = timeUnit.toMillis(durationAmount);
long time2 = duration.timeUnit.toMillis(duration.durationAmount);
return time1 == time2;
} else {
return false;
}
}
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return timeUnit == null ? -1 : (int)timeUnit.toMillis(durationAmount);
}
}