view src/treecms/memory/OnMemoryForest.java @ 11:85061e874775

commit
author shoshi
date Fri, 06 May 2011 00:42:57 +0900
parents 17ed97ca9960
children 22cd920986c5
line wrap: on
line source

package treecms.memory;

import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import treecms.api.Forest;
import treecms.api.Node;
import treecms.api.NodeData;
import treecms.api.NodeID;
import treecms.api.Tree;
import treecms.api.MonotonicTree;
import treecms.tree.id.AbstractRandomNodeID;

/**
 * Forestのオンメモリ上の実装.
 * @author shoshi
 */
public class OnMemoryForest implements Forest
{
	//Nodeのマップ
	Map<NodeID,OnMemoryNode> m_table;
	//最新版Nodeのマップ
	Map<String,OnMemoryNode> m_tipTable;
	
	//MainTreeのUUID
	String m_mainID;
	
	/**
	 * コンストラクタ
	 */
	public OnMemoryForest()
	{
		m_table = new ConcurrentHashMap<NodeID,OnMemoryNode>();
		m_tipTable = new ConcurrentHashMap<String,OnMemoryNode>();
		
		m_mainID = createNode(null,null).getID().getUUID();
	}
	
	/**
	 * 新しくNodeを作成します
	 * @param _id Nodeに適用されるNodeID
	 * @param _newData Nodeが保持するNodeData
	 * @return 作成されたOnMemoryNode
	 */
	public OnMemoryNode createNode(NodeID _id,NodeData _newData)
	{
		NodeID newID = (_id != null) ? _id : createID();
		NodeData newData = (_newData != null) ? _newData : new NodeData();
		
		//newIDとnewDataを元にOnMemoryNodeを生成する.
		OnMemoryNode newNode = new OnMemoryNode(this,newID,newData);
		
		//登録
		m_table.put(newID,newNode);
		m_tipTable.put(newID.getUUID(),newNode);
		
		return newNode;
	}
	
	/**
	 * 新しいNodeIDを作成します
	 * @return 新しいNodeID
	 */
	private NodeID createID()
	{
		return new RandomNodeID(null);
	}

	/**
	 * NodeIDに対応するNodeを取得します 
	 * @return NodeIDに対応するNode
	 */
	@Override
	public Node get(NodeID _id)
	{
		return m_table.get(_id);
	}
	
	/**
	 * あるNodeをルートとしてTreeのオブジェクトを取得します。
	 * @param _id 木のルートとなるNodeのNodeID
	 * @return Tree
	 */
	@Override
	public Tree getTree(Node _node)
	{
		Forest forest = _node.getForest();
		if(forest != this){
			throw new IllegalArgumentException();
		}
		
		return new OnMemoryTree((OnMemoryNode)_node);
	}
	
	/**
	 * あるNodeをルートとしたTreeを非破壊的に編集するTreeEditorを取得します。
	 * @param _id 木のルートとなるNodeのNodeID
	 * @return TreeEditor
	 */
	@Override
	public MonotonicTree getMonotonicTree(Tree _tree)
	{
		Forest forest = _tree.getRoot().getNode().getForest();
		if(forest != this){
			throw new IllegalArgumentException();
		}
		
		return new OnMemoryMonotonicTree((OnMemoryTree)_tree);
	}
	
	/**
	 * 新しくNodeを作成します.
	 * @return 新しいNode
	 */
	@Override
	public Node create()
	{
		return createNode(null,null);
	}

	/**
	 * NodeDataを保持した新しいNodeを作成します
	 * @return NodeDataを保持した新しいNode 
	 */
	@Override
	public Node create(NodeData _data)
	{
		return createNode(null,_data);
	}

	/**
	 * 最新のNodeを取得します.
	 * @return UUIDに対応する最新のNode
	 */
	@Override
	public Node getTip(String _uuid)
	{
		return m_tipTable.get(_uuid);
	}

	/**
	 * MainTreeを取得します。
	 * @return このForestのMainTree
	 */
	@Override
	public Tree getMainTree()
	{
		return new OnMemoryTree(m_tipTable.get(m_mainID));
	}
	
	/**
	 * ランダムにバージョン番号を生成するNodeIDです.ファクトリを内包します.
	 * @author shoshi
	 */
	private static class RandomNodeID extends AbstractRandomNodeID
	{
		/**
		 * UUID
		 */
		private String m_uuid;
		
		/**
		 * バージョン番号(ランダム値)
		 */
		private long m_version;
		
		/**
		 * コンストラクタ
		 * @param _uuid 継承するUUID
		 */
		public RandomNodeID(String _uuid)
		{
			m_uuid = (_uuid != null) ? _uuid : UUID.randomUUID().toString();
			m_version = (new Random()).nextLong();
		}

		/**
		 * 新しいRandomNodeIDを作成します。
		 * @return 新しいRandomNodeID
		 */
		@Override
		public NodeID create()
		{
			return new RandomNodeID(null);
		}

		/**
		 * UUIDを継承したRandomNodeIDを作成します.
		 * @return 新しいRandomNodeID
		 */
		@Override
		public NodeID update()
		{
			return new RandomNodeID(m_uuid);
		}

		/**
		 * UUIDを取得します.
		 * @return UUID
		 */
		@Override
		public String getUUID()
		{
			return m_uuid;
		}

		/**
		 * バージョンを取得します.
		 * @return バージョン
		 */
		@Override
		public String getVersion()
		{
			return Long.toHexString(m_version);
		}
	}
}