package org.maachang.session.client.net.protocol ;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.maachang.session.engine.PersistenceDefine;
import org.maachang.util.ArrayBinary;
import org.maachang.util.ConvertParam;
import org.maachang.util.SerializableUtil;

/**
 * セッションIDに対して要素を追加.
 * 
 * @version 2008/05/25
 * @author masahito suzuki
 * @since PersistenceSession 1.00
 */
public class ClPutSessionKeyProtocol extends ClientProtocol {
    
    /**
     * セッションID.
     */
    private String sessionId = null ;
    
    /**
     * 要素キー名.
     */
    private String key = null ;
    
    /**
     * 要素Value.
     */
    private Object value = null ;
    
    /**
     * コンストラクタ.
     */
    public ClPutSessionKeyProtocol() {
    }
    
    /**
     * オブジェクト生成.
     */
    public void create( String sessionId,String key,Object value )
        throws Exception {
        if( sessionId == null ||
            ( sessionId = sessionId.trim() ).length() != PersistenceDefine.SESSION_KEY_LENGTH ) {
            throw new IllegalArgumentException( "指定されたセッションIDは不正です" ) ;
        }
        if( key == null || ( key = key.trim() ).length() <= 0 ) {
            throw new IllegalArgumentException( "指定された要素キーは不正です" ) ;
        }
        if( value == null ) {
            throw new IllegalArgumentException( "指定された要素は不正です" ) ;
        }
        else if( value instanceof String && ( ( String )value ).length() <= 0 ) {
            throw new IllegalArgumentException( "指定された要素は不正です" ) ;
        }
        else if( value instanceof byte[] && ( ( byte[] )value ).length <= 0 ) {
            throw new IllegalArgumentException( "指定された要素は不正です" ) ;
        }
        else if( ( value instanceof Serializable ) == false ||
            value instanceof Map || value instanceof List ) {
            throw new IllegalArgumentException( "指定された要素はシリアライズ可能な形式ではありません" ) ;
        }
        this.sessionId = sessionId ;
        this.key = key ;
        this.value = value ;
    }
    
    /**
     * オブジェクトクリア.
     */
    public void clear() {
        super.clear() ;
        sessionId = null ;
        key = null ;
        value = null ;
    }
    
    /**
     * クライアントプロトコルタイプを取得.
     * @return int クライアントプロトコルタイプが返されます.
     */
    public int getProtocolType() {
        return TYPE_PUT_VALUE ;
    }
    
    /**
     * セッションIDを取得.
     * @return String セッションIDが返されます.
     */
    public String getSessionId() {
        return sessionId ;
    }
    
    /**
     * 要素キー名を取得.
     * @return String 要素キー名が返されます.
     */
    public String getKey() {
        return key ;
    }
    
    /**
     * 要素Valueを取得.
     * @return Object 要素Valueが返されます.
     */
    public Object getValue() {
        return value ;
    }
    
    /**
     * 送信データを作成.
     * @return value 送信データが返されます.
     * @exception Exception 例外.
     */
    public byte[] getSendData() throws Exception {
        ArrayBinary b = new ArrayBinary() ;
        b.write( ConvertParam.convertInt( getProtocolType() ) ) ;
        byte[] valBin = sessionId.getBytes( "UTF8" ) ;
        b.write( ConvertParam.convertInt( valBin.length ) ) ;
        b.write( valBin ) ;
        valBin = key.getBytes( "UTF8" ) ;
        b.write( ConvertParam.convertInt( valBin.length ) ) ;
        b.write( valBin ) ;
        
        if( value instanceof String ) {
            valBin = ( ( String )value ).getBytes( "UTF8" ) ;
            b.write( ConvertParam.convertInt( valBin.length+1 ) ) ;
            b.write( new byte[]{ ( byte )VALUE_TYPE_STRING } ) ;
            b.write( valBin ) ;
        }
        else if( value instanceof byte[] ) {
            b.write( ConvertParam.convertInt( ( ( byte[] )value ).length+1 ) ) ;
            b.write( new byte[]{ ( byte )VALUE_TYPE_BINARY } ) ;
            b.write( ( byte[] )value ) ;
        }
        else {
            valBin = SerializableUtil.toBinary( ( Serializable )value ) ;
            b.write( ConvertParam.convertInt( valBin.length+1 ) ) ;
            b.write( new byte[]{ ( byte )VALUE_TYPE_OBJECT } ) ;
            b.write( valBin ) ;
        }
        return b.getBinary() ;
    }
    
    /**
     * 処理結果の内容を設定.
     * @param value 処理結果の内容を設定します.
     * @param p オフセット値を設定します.
     */
    public void setResult( byte[] value,int p ) throws Exception {
        this.result = null ;
    }
}

