package org.maachang.session.engine ;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * キャッシュValue情報.
 *  
 * @version 2008/05/25
 * @author  masahito suzuki
 * @since  PersistenceSession 1.00
 */
class CacheValue {
    
    /**
     * 格納時間.
     */
    private long lastMod = -1L ;
    
    /**
     * キャッシュ内要素.
     */
    private List<CacheChild> values = null ;
    
    /**
     * コンストラクタ.
     */
    protected CacheValue() {
        this.lastMod = System.currentTimeMillis() ;
        this.values = Collections.synchronizedList( new ArrayList<CacheChild>() ) ;
    }
    
    /**
     * デストラクタ.
     */
    protected void finalize() throws Exception {
        destroy() ;
    }
    
    /**
     * オブジェクト破棄.
     */
    public void destroy() {
        lastMod = -1L ;
        values = null ;
    }
    
    /**
     * 指定Keyを検索.
     */
    protected int search( String key ) {
        int len = values.size() ;
        for( int i = 0 ; i < len ; i ++ ) {
            CacheChild ch = values.get( i ) ;
            if( ch != null && key.equals( ch.getKey() ) ) {
                return i ;
            }
        }
        return -1 ;
    }
    
    /**
     * 最終更新時間を取得.
     */
    private synchronized long getLastMod() {
        return lastMod ;
    }
    
    /**
     * 最終更新時間を更新.
     */
    private synchronized void updateLastMod() {
        lastMod = System.currentTimeMillis() ;
    }
    
    /**
     * 情報追加.
     * @param key 対象のKeyを設定します.
     * @param value 対象の要素を設定します.
     */
    public void put( String key,byte[] value ) {
        if( key == null || ( key = key.trim() ).length() <= 0 ||
            value == null || value.length <= 0 ) {
            return ;
        }
        synchronized( this ) {
            int n = search( key ) ;
            if( n <= -1 ) {
                CacheChild ch = new CacheChild( key,value ) ;
                values.add( ch ) ;
            }
            else {
                values.get( n ).setValue( value ) ;
            }
            updateLastMod() ;
        }
    }
    
    /**
     * 情報削除.
     * @param key 削除対象のKeyを設定します.
     */
    public void remove( String key ) {
        if( key == null || ( key = key.trim() ).length() <= 0 ) {
            return ;
        }
        synchronized( this ) {
            int n = search( key ) ;
            if( n >= 0 ) {
                values.remove( n ) ;
            }
            updateLastMod() ;
        }
    }
    
    /**
     * 情報削除.
     */
    protected void remove( int no ) {
        if( no <= -1 || no >= values.size() ) {
            return ;
        }
        synchronized( this ) {
            values.remove( no ) ;
            updateLastMod() ;
        }
    }
    
    /**
     * 情報取得.
     * @param key 取得対象のKeyを設定します.
     * @return byte[] 対象のValueが返されます.
     */
    public byte[] get( String key ) {
        if( key == null || ( key = key.trim() ).length() <= 0 ) {
            return null ;
        }
        byte[] ret = null ;
        synchronized( this ) {
            int n = search( key ) ;
            if( n >= 0 ) {
                ret = values.get( n ).getValue() ;
            }
            updateLastMod() ;
        }
        return ret ;
    }
    
    /**
     * 情報削除.
     */
    protected byte[] get( int no ) {
        if( no <= -1 || no >= values.size() ) {
            return null ;
        }
        byte[] ret = null ;
        synchronized( this ) {
            CacheChild ch = values.get( no ) ;
            if( ch != null ) {
                ret = ch.getValue() ;
            }
            updateLastMod() ;
        }
        return ret ;
    }
    
    /**
     * 指定Keyが存在するかチェック.
     * @param key 対象のKeyを設定します.
     * @return boolean [true]の場合、情報は存在します.
     */
    public boolean containsKey( String key ) {
        if( key == null || ( key = key.trim() ).length() <= 0 ) {
            return false ;
        }
        if( search( key ) >= 0 ) {
            return true ;
        }
        return false ;
    }
    
    /**
     * データサイズを取得.
     * @return int データサイズが返されます.
     */
    public int size() {
        return values.size() ;
    }
    
    /**
     * 最終更新日を取得.
     * @return long 最終更新日が返されます.
     */
    public long getLastTime() {
        return getLastMod() ;
    }
}

/**
 * キャッシュ要素.
 */
class CacheChild {
    private String key = null ;
    private byte[] value = null ;
    
    protected CacheChild() {
        
    }
    
    protected CacheChild( String key,byte[] value ) {
        this.key = key ;
        this.value = value ;
    }
    
    protected void finalize() throws Exception {
        this.key = null ;
        this.value = null ;
    }
    
    public void setKey( String key ) {
        this.key = key ;
    }
    
    public String getKey() {
        return key ;
    }
    
    public void setValue( byte[] value ) {
        this.value = value ;
    }
    
    public byte[] getValue() {
        return value ;
    }
}

