view src/treecms/memory/OnMemoryTreeEditor.java @ 8:f96193babac0

changed byte[] to ByteBuffer added TreeEditor.updateTree(Node,NodeData,Node[]) for node path is known. added GUIEditor
author shoshi
date Thu, 31 Mar 2011 02:08:44 +0900
parents fc19e38b669b
children 17ed97ca9960
line wrap: on
line source

package treecms.memory;

import java.util.LinkedList;
import treecms.api.Node;
import treecms.api.NodeData;
import treecms.api.NodeID;
import treecms.api.TreeEditor;
import treecms.merger.Merger;
import treecms.merger.ReplaceMerger;
import treecms.tree.util.NodePathFinder;
import treecms.tree.util.PathNotFoundException;

/**
 * 木構造を非破壊的に編集するオンメモリの実装です。 
 * @author shoshi
 */
final class OnMemoryTreeEditor implements TreeEditor
{
	private OnMemoryTree m_tree;
	private OnMemoryNode m_backup;
	private OnMemoryNode m_root;
	
	/**
	 * コンストラクタです。
	 * @param _tree 監視の対象とするOnMemoryTree
	 */
	public OnMemoryTreeEditor(OnMemoryTree _tree)
	{
		m_root = (OnMemoryNode)_tree.getRoot();
		m_backup = m_root;
	}
	
	/**
	 * 変更を元の木構造にコミットします。この操作はコミット先が先にアップデートされていた場合は失敗します
	 * @param _force trueの場合は強制的に置き換えます。
	 * @return コミットが成功した場合true
	 */
	@Override
	public boolean commit(boolean _force)
	{
		return m_tree.compareAndSwapRootNode(m_backup,m_root,_force);
	}

	/**
	 * 監視している木構造のルートと自身のルートに上書きします。 
	 * @return true
	 */
	@Override
	public boolean pull()
	{
		m_root = (OnMemoryNode)m_tree.getRoot();
		m_backup = m_root;
		return true;
	}

	/**
	 * 監視している木構造が更新されていないか確認します。
	 * @return 更新されている場合true、されていない場合はfalse
	 */
	@Override
	public boolean check()
	{
		if(m_tree.getRoot().getID().equals(m_root.getID())){
			return false;
		}
		return true;
	}

	/**
	 * 監視している木構造の内容を自分の木構造にマージします
	 * 最新版の木構造とマージする場合は、先にpull()を実行してください。
	 */
	@Override
	public void merge()
	{
		Merger merger = new ReplaceMerger();
		m_root = (OnMemoryNode)merger.merge(m_backup,m_root);
	}
	
	/**
	 * 実装しろ
	 */
	@Override
	public synchronized Node updateTree(Node _target,NodeData _newData,Node[] _path) throws PathNotFoundException
	{
		//パスの正当性の検証
		if(_path.length == 0){
			throw new PathNotFoundException("node path is empty");
		}else{
			//ここでごちゃごちゃする
			//めんどくさい
		}
		
		
		
		
		
		return null;
	}
	
	/**
	 * 木構造を非破壊的に更新します.
	 * @param _target 更新する対象
	 * @param _newData 更新に適用されるNodeData
	 * @return 更新されたNode
	 * @throws ルートNodeから_targetまでのパスが見つからない場合、PathNotFoundException
	 */
	@Override
	public synchronized Node updateTree(Node _target,NodeData _newData) throws PathNotFoundException
	{
		NodePathFinder finder = new NodePathFinder(m_root,_target);
		OnMemoryForest forest = (OnMemoryForest)m_tree.getForest();
		
		for(Node path : finder){
			NodeData data = path.getData();
			NodeID newID = path.getID().update();
			Node clone = forest.createNode(newID,data);
		}
		
		return null;
	}
	
	private LinkedList<OnMemoryNode> findAndClone(OnMemoryNode _parent,OnMemoryNode _target,NodeData _newData)
	{
		OnMemoryForest forest = (OnMemoryForest)_target.getForest();
		if(_parent.getID().equals(_target.getID())){
			LinkedList<OnMemoryNode> path = new LinkedList<OnMemoryNode>();
			OnMemoryNode clone = forest.createNode(_target.getID().update(),_newData);
			path.addFirst(clone);
			return path;
		}
		
		for(Node child : _parent.children()){
			LinkedList<OnMemoryNode> path = findAndClone((OnMemoryNode)child,_target,_newData);
			if(path != null){
				path.addFirst(_parent);
				return path;
			}
		}
		
		return null;
	}
	
	/**
	 * ルートNodeを取得します。
	 * @return この木構造のルートNode
	 * */
	@Override
	public Node getRoot()
	{
		return m_root;
	}
}