/*
 * @(#)FElement.java
 *
 * Copyright 2001 by Intelligent Technology Inc. All rights reserved.
 */

package jp.co.iti.fagot.fob;

import java.util.Vector;

/**
 * FElementはデータクラスです。
 * undoable,sirializeデータクラス。
 *
 * 【仕様】
 * 基本的にundoなどのためにデータのカプセル化をインプリメントする
 * そのため、set,getメソッド以外のデータ操作は定義しない
 * getメソッドでは変更されても構わないようにデータの複製を返却する
 * setメソッドではundoオブジェクトを生成した後、データを変更する
 * ただし、DVectorは性質上複製を返しにくいので、データ操作メソッドを
 * いくつか定義する
 *
 * null値の設定も可能
 *
 * @author  千曳秀喜
 * @version 1.01 2001/01/07
 */
public class FElement {

	/**
	 * コンストラクタ
	 */
	public FElement() {
	}

	/**
	 * コンストラクタ
	 */
	public FElement(Object data) {
	setData( data );
	}

	/**
	 * マネージャの取得
	 */
	public FobManager getFobManager() {
	return ( mMgr ) ;
	}

	/**
	 * マネージャの設定
	 * @param mgr マネージャ
	 * @param usrData ユーザデータ(任意のユーザデータ)
	 */
	public void setFobManager( FobManager mgr, Object usrData ) {
	mMgr     = mgr ;
	mUsrData = usrData;
	}

	/**
	 * ユーザデータの取得
	 */
	public Object getUsrData() {
	return ( mUsrData ) ;
	}

	/**
	 * ユーザデータの設定
	 * @param usrData ユーザデータ(任意のユーザデータ)
	 */
	public void setUsrData( Object usrData ) {
	mUsrData = usrData;
	}

	/**
	 * 値の取得
	 * 値は、通常派生クラスの型として取り出されるので、ここはprotected
	 */
	protected Object getData() {
	return ( mData ) ;
	}

	/**
	 * null値か？
	 */
	public boolean isNull() {
	return ( mData == null );
	}

	/**
	 * 値の設定
	 */
	public void setData(Object data) {
	if ( isNull() && data==null ) {
		return;
	} else if ( (!isNull()) && mData.equals(data) ) {
		return;
	}
	if ( mMgr != null ) {
		mMgr.push( new FUndoElement(this,mData,data) );
	}
	setDataNoUndo( data );
	}

	/**
	 * 値の設定
	 */
	public void setDataNoUndo(Object data) {
	if ( equals(data) ) {
		return;
	}
	mData = data ;
	}

	/**
	 * 値の設定
	 */
	public void empty() {
	setData( null );
	}

	/**
	 * 等しいか？
	 */
	public boolean equals(Object data) {
	if ( mData == data ) {
		return true;
	}
	if ( mData!= null && mData.equals( data ) ) {
		return true;
	}
	return false;
	}

	//## CLONE ########################################################
	/**
	 * 複製の作成（マネージャは複製しない）
	 */
	public Object clone() {
	Object obj = createClone();
	copyAttribute( obj );
	return obj;
	}

	/**
	 * 複製インスタンスの作成
	 * 各実現クラスにおいてインスタンスを生成する
	 * 仮想クラス（およびインスタンス化されないクラス）ではnullを返す
	 */
	public Object createClone() {
	return null;
	}

	/**
	 * アトリビュートの複製
	 * @param obj 複製先のオブジェクト
	 */
	public void copyAttribute( Object obj ) {
	((FElement)obj).setData( getData() );
	}

	//## アトリビュート################################################
	/**
	 * FobManager
	 */
	protected FobManager mMgr  = null ;

	/**
	 * 値
	 */
	protected Object   mData = null ;

	/**
	 * ユーザデータ(任意の値)
	 */
	protected Object   mUsrData = null ;

	//#################################################################
	//## サブクラス：アンドゥオブジェクト##############################
	//#################################################################
	/**
	 * FElement用undoオブジェクト
	 */
	public class FUndoElement implements IFUndoElement {

	/**
	 * コンストラクタ
	 * @param org オリジナルオブジェクト
	 * @param oldVal 古い値
	 * @param newVal 新しい値
	 */
	public FUndoElement(FElement org, Object oldVal, Object newVal) {
	mOrg    = org    ;
	mOldVal = oldVal ;
	mNewVal = newVal ;
	}

	/**
	 * アンドゥ
	 */
	public void undo() {
	mOrg.setDataNoUndo(mOldVal);
	}

	/**
	 * リドゥ
	 */
	public void redo() {
	mOrg.setDataNoUndo(mNewVal);
	}

	/**
	 * オリジナルオブジェクトの取得
	 */
	public void getFobs( Vector items ) {
	items.add( mOrg );
	}

	//## アトリビュート################################################
	/**
	 * オリジナルオブジェクト
	 */
	protected FElement mOrg    = null ;

	/**
	 * 古い値
	 */
	protected Object   mOldVal = null ;
	
	/**
	 * 新しい値
	 */
	protected Object   mNewVal = null ;

	}
}
