/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This 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 software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.cache;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;


/**
 * Wraps cache keys, which are sorted according to creation time. This may be
 * useful for cache eviction policies, which may want to evict the oldest
 * entries first. If the TreeMap is already sorted, these policies do not have
 * to iterate through the entire map.
 * @author Bela Ban
 * @version $Revision: 1.1.2.1 $
 * todo Test null values
 */
public class CacheKey implements Comparable, Externalizable {
    Object key=null;
    long timestamp=System.currentTimeMillis();

    /**
     * Constructor for CacheKey. Used for externalization
     */
    public CacheKey() {
        super();
    }

    /** Constructor, takes a key */
    public CacheKey(Object key) {
        this.key=key;
    }


    /**
     * Returns the key.
     * @return Object
     */
    public Object getKey() {
        return key;
    }

    /**
     * Sets the key.
     * @param key The key to set
     */
    public void setKey(Object key) {
        this.key=key;
    }


    public long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(long new_timestamp) {
        timestamp=new_timestamp;
    }

    public int hashCode() {
        return key != null ? key.hashCode() : 0;
    }


    /** Compares by comparing keys, <em>not</em> timestamps */
    public boolean equals(Object obj) {
        // return compareTo(obj) == 0;

        CacheKey other=(CacheKey)obj;
        if(key == null && other.key == null)
            return true;
        return key.equals(other.key);
    }

    /** Use by the TreeMap (in CacheImpl) to determine sort order. The order is
     * on timestamp.
     * @see java.lang.Comparable#compareTo(Object)
     */
    public int compareTo(Object obj) {
        long ts2=((CacheKey)obj).timestamp;
        return timestamp == ts2 ? 0 : (timestamp < ts2 ? -1 : 1);
    }

    public String toString() {
        return key != null ? key.toString() : null;
    }


    /**
     * Only read the value; the timestamp is already set (in the null
     * constructor)
     * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
     */
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        if(in.readBoolean()) {
            key=in.readObject();
        }
    }

    /**
     * We only send the value, not the timestamp. The timestamp will be
     * recreated in the other member processes (current time there (which may
     * be different than ours)).
     * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
     */
    public void writeExternal(ObjectOutput out) throws IOException {
        if(key != null) {
            out.writeBoolean(true);
            out.writeObject(key);
        }
        else {
            out.writeBoolean(false);
        }
    }

}
