/* Open Source Java Caching Service
* Copyright (C) 2002 Frank Karlstr�m
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* The author can be contacted by email: fjankk@sourceforge.net
*/
package org.fjank.jcache;
import java.io.Serializable;
import javax.util.jcache.Attributes;
import javax.util.jcache.CacheEventListener;
import javax.util.jcache.CacheLoader;
import javax.util.jcache.InvalidArgumentException;
/**
* This class defines the attributes an object in the cache can have.
*/
public final class AttributesImpl implements Cloneable, Serializable, Attributes {
private static final int ONE_DAY = 24;
private static final int ONE_HOUR = 60;
private static final int ONE_MINUTE = 60;
/** the time the associated CacheObject was created. */
private long createTime = System.currentTimeMillis();
/** the default time the associated CacheObject should live in the cache */
private long defaultTTL = -1;
/**
* Is used to specify wich attributes should be set in the attributes
* object. The differnet attributes wich is valid is defined as public
* static variables in the {@link Attributes}class.
*/
private long flags;
/** the time the associated CacheObject should be idle in the cache */
private long idleTime;
/** the CacheListener for the associated CacheObject */
private transient CacheEventListener listener;
/** the CacheLoader for the associated CacheObject */
private transient CacheLoader loader;
/** the size for the associated CacheObject */
private int size;
/** the time the associated CacheObject should be live the cache */
private long timeToLive = -1;
/** the version of the associated CacheObject */
private long version;
/**
* Creates new Attributes
*/
public AttributesImpl() {
}
public AttributesImpl(Attributes attributes) {
this.defaultTTL=attributes.getDefaultTimeToLive();
this.idleTime=attributes.getIdleTime();
this.listener=attributes.getListener();
this.loader=attributes.getLoader();
this.size=attributes.getSize();
this.timeToLive=attributes.getTimeToLive();
this.version=attributes.getVersion();
long flags = 0;
if(attributes.isSet(Attributes.DISTRIBUTE)) {
flags |= Attributes.DISTRIBUTE;
}
if(attributes.isSet(Attributes.NOFLUSH)) {
flags |= Attributes.NOFLUSH;
}
if(attributes.isSet(Attributes.REPLY)) {
flags |= Attributes.REPLY;
}
if(attributes.isSet(Attributes.SYNCHRONIZE)) {
flags |= Attributes.SYNCHRONIZE;
}
if(attributes.isSet(Attributes.SPOOL)) {
flags |= Attributes.SPOOL;
}
if(attributes.isSet(Attributes.GROUP_TTL_DESTROY)) {
flags |= Attributes.GROUP_TTL_DESTROY;
}
if(attributes.isSet(Attributes.ORIGINAL)) {
flags |= Attributes.ORIGINAL;
}
this.flags=flags;
}
public void applyAttributes(Attributes attributes) {
this.idleTime = attributes.getIdleTime();
this.timeToLive = attributes.getTimeToLive();
this.defaultTTL = attributes.getDefaultTimeToLive();
CacheEventListener listener = attributes.getListener();
setListener(Attributes.INVALIDATE_EVENT, listener);
}
public boolean equals(Object arg0) {
if (arg0 instanceof AttributesImpl) {
AttributesImpl obj = (AttributesImpl) arg0;
if (defaultTTL != obj.defaultTTL)
return false;
if (flags != obj.flags)
return false;
if (listener != obj.listener)
return false;
if (loader != obj.loader)
return false;
if (size != obj.size)
return false;
if (timeToLive != obj.timeToLive)
return false;
if (version != obj.version)
return false;
return true;
}
return super.equals(arg0);
}
/**
* returns the time the object was loaded into the cache. The time is the
* number of milliseconds since midnight, January 1, 1970 (UTC).
*
* @return the time the object was loaded into the cache. The time is the
* number of milliseconds since midnight, January 1, 1970 (UTC).
*/
public long getCreateTime() {
return createTime;
}
public long getDefaultTimeToLive() {
return defaultTTL;
}
/**
* returns the current value for the idle time interval.
*
* @return the current value for the idle time interval.
*/
public long getIdleTime() {
return idleTime;
}
/**
* Gets the CacheEventListener.
* @author Philippe Fajeau
* @return The CacheEventListener.
*/
public CacheEventListener getListener() {
return listener;
}
/**
* returns the {@link CacheLoader}attribute.
*
* @return the {@link CacheLoader}attribute.
*/
public CacheLoader getLoader() {
return loader;
}
/**
* returns the size of the object. this size is set by the {@link
* #setSize(int)} method, or in the case of StreamAccess objects, the size
* is calculated by the cache.
* @todo create and implement an online size calculator.
* @return the size of the object, or 0 if the size has not been set.
*/
public int getSize() {
return size;
}
/**
* returns the current value for the time to live interval.
*
* @return the current value for the time to live interval.
*/
public long getTimeToLive() {
if (defaultTTL != -1 && timeToLive == -1) {
return defaultTTL;
}
return timeToLive;
}
/**
* returns the current value of version.
*
* @return the current value of version.
*/
public long getVersion() {
return version;
}
/**
* Checks wether the flags are set or not.
*
* @param theFlags the flags to be checked. may be OR-ed together, for wich
* this method will return true only if all flags are set.
*
* @return true if the specified attribute is set, false otherwise.
*/
public boolean isSet(final long theFlags) {
return ((this.flags | theFlags) ^ this.flags) == 0;
}
/**
* resets the Attributes to its default values. The attributes wich are
* reset are expiration time attributes, time to live, default time to
* live, idle time and event handlers.
*
* @todo This method should be package private, thus this class should be
* moved to org.fjank.jcache, an interface should be extracted, and
* that should be public, and in this package.
*/
public void reset() {
AttributesImpl def = new AttributesImpl();
this.idleTime = def.idleTime;
this.timeToLive = def.timeToLive;
this.defaultTTL = def.defaultTTL;
this.listener = def.listener;
}
/**
* Sets the createTime.
*
* @param aCreateTime The createTime to set
*/
public void setCreateTime(final long aCreateTime) {
if (aCreateTime < 0) {
return;
}
this.createTime = aCreateTime;
}
/**
* Will set the maximum time the associated cache object will stay in the
* cache before it is invalidated. For regions and groups, this will
* establish a default time to live that is applied individually to each
* member in the group or region. It will not cause the entire group or
* region to time out as a whole. For individual objects, the default time
* to live is equivalent with time to live. If both are set the default time
* to live is ignored. The time starts when the object is loaded into the
* cache(by the {@link CacheLoader}objector put by the {@link
* CacheAccess#replace(Object, Object)}) or when the time to live attribute
* is set by the {@link CacheLoader#setAttributes(Object,Attributes)}
* method.
*
* @param ttl the time to live in seconds. The {@link #timeToSeconds(int,
* int, int, int)} can be used to convert days, hours, minutes to
* secounds.
*
* @throws InvalidArgumentException if a negative value for ttl is supplied.
*/
public void setDefaultTimeToLive(final long ttl) throws InvalidArgumentException {
if (ttl < 0) {
throw new InvalidArgumentException("Default time to live must be a positive number.");
}
this.defaultTTL = ttl;
}
/**
* Is used to specify wich attributes should be set in the attributes
* object. The different attributes wich is valid is defined as public
* static variables in the {@link Attributes}class.
*
* @param theFlags The attributes to set. the attributes may be OR-ed
* together. I.e. Attributes.DISTRIBUTE | Attributes.SYNCHRONIZE
* Invalid flags are silently ignored. To reset all flags you use
* 0 as a parameter. I.e. setFlags(0)
*/
public void setFlags(final long theFlags) {
if (theFlags < 0) {
return;
}
this.flags = theFlags;
}
/**
* sets the maximum time the associated cache object will remain in the
* cache without being referenced before it is invalidated.
*
* @param idle is in seconds. The {@link #timeToSeconds(int, int, int,int)}
* can be used to convert days, hours, minutes to secounds.
*
* @throws InvalidArgumentException if a negative value for idle is
* supplied.
*/
public void setIdleTime(final long idle) throws InvalidArgumentException {
if (idle < 0) {
throw new InvalidArgumentException("Idle time must be a positive number.");
}
this.idleTime = idle;
}
/**
* Register an event listener object to be executed when the specified event
* occurs with relationship to the associated object. Currently the only
* invalidate event being monitored is Attributes.INVALIDATE_EVENT. If
* invalid parameters are passed such as invalid events, or null as
* listener, this method silently returns without doing any changes to this
* object.
*
* @param event The event to listen for.
* @param aListener the listener to fire when the event occurs.
*
*@todo Should these Attributes only have one Listener, or should several be
* supported?
*/
public void setListener(final int event, final CacheEventListener aListener) {
if ((event == INVALIDATE_EVENT) && (aListener != null)) {
this.listener = aListener;
}
}
/**
* Will associate a loader object with this object.
*
* @param aLoader The loader to set. This parameter can be null.
*/
public void setLoader(final CacheLoader aLoader) {
this.loader = aLoader;
}
/**
* Is used to specify the size in bytes of the object being cached. This is
* used to determine when the cache capacity is reached. If the cache is not
* using object size to determine the capacity (It can also use object
* counts) this value is ignored.
*
* @param aSize the size to be set. if this parameter is smaller than zero,
* this method silently returns.
*/
public void setSize(final int aSize) {
if (aSize < 0) {
return;
}
this.size = aSize;
}
/**
* Will set the maximum time the associated cache object will stay in the
* cache before it is invalidated. The time starts when the object is loaded
* into the cache(by the {@link CacheLoader}object or put by the
* {@link CacheAccess#replace(Object, Object)}) or when the time to live
* attribute is set by the {@link CacheLoader#setAttributes(Object,
* Attributes)} method.
*
* @param ttl the time to live in seconds. The {@link #timeToSeconds(int,
* int, int, int)} can be used to convert days, hours, minutes to
* seconds.
*
* @throws InvalidArgumentException if a negative value for ttl is supplied.
*/
public void setTimeToLive(final long ttl) throws InvalidArgumentException {
if (ttl < 0) {
throw new InvalidArgumentException("Time to live must be a positive number.");
}
this.timeToLive = ttl;
}
/**
* Sets the version attribute. Is only maintained for user convenience. It
* is not used internally by the cache.
*
* @param aVersion the version number to set.
*/
public void setVersion(final long aVersion) {
this.version = aVersion;
}
/**
* Will convert the time specified into seconds.
*
* @param days number of days.
* @param hours number of hours.
* @param minutes number of minutes.
* @param seconds number of seconds.
*
* @return the converted time in seconds.
*
* @throws InvalidArgumentException if any of the parameters are negative
* values.
*/
public long timeToSeconds(final int days, final int hours, final int minutes, final int seconds) throws InvalidArgumentException {
if (days < 0) {
throw new InvalidArgumentException("Days must be larger than zero.");
}
if (hours < 0) {
throw new InvalidArgumentException("Hours must be larger than zero.");
}
if (minutes < 0) {
throw new InvalidArgumentException("Minutes must be larger than zero.");
}
if (seconds < 0) {
throw new InvalidArgumentException("Seconds must be larger than zero.");
}
return seconds + (ONE_MINUTE * minutes) + (ONE_MINUTE * ONE_HOUR * hours) + (ONE_MINUTE * ONE_HOUR * ONE_DAY * days);
}
/**
* returns these Attributes as a String.
*
* @return these Attributes as a String.
*/
public String toString() {
return "Attributes {ttl:" + timeToLive + '}'; //$NON-NLS-1$
}
}