view src/treecms/memory/OnMemoryMonotonicTreeNode.java @ 21:f3150b37f9be

commit
author shoshi
date Mon, 06 Jun 2011 21:49:04 +0900
parents 084de6909451
children fa784faafc78
line wrap: on
line source

package treecms.memory;

import java.nio.ByteBuffer;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;

import treecms.api.Forest;
import treecms.api.MonotonicTreeNode;
import treecms.api.Node;
import treecms.api.NodeAttributes;
import treecms.api.NodeChildren;
import treecms.api.NodeID;
import treecms.tree.util.NodeChildrenImpl;
import treecms.tree.util.NodeData;

/**
 * SingleLinkedなNodeをラップしたDoubleLinkedなNodeの実装です.
 * @author shoshi
 */
public class OnMemoryMonotonicTreeNode implements MonotonicTreeNode
{
	private Node m_node;
	
	private static final AtomicReferenceFieldUpdater<OnMemoryMonotonicTreeNode,OnMemoryMonotonicTreeNode> m_parentUpdater 
		= AtomicReferenceFieldUpdater.newUpdater(OnMemoryMonotonicTreeNode.class,OnMemoryMonotonicTreeNode.class,"m_parent");
	
	private OnMemoryMonotonicTreeNode m_parent;
	
	private final Map<String,OnMemoryMonotonicTreeNode> m_cache;
	
	public OnMemoryMonotonicTreeNode(OnMemoryNode _target,OnMemoryMonotonicTreeNode _parent)
	{
		m_node  = _target;
		m_parent = _parent;
		m_cache = new ConcurrentHashMap<String,OnMemoryMonotonicTreeNode>();
	}
	
	@Override
	public NodeID getID()
	{
		return m_node.getID();
	}

	@Override
	public Forest getForest()
	{
		return m_node.getForest();
	}

	@Override
	public MonotonicTreeNode getParent()
	{
		return m_parent;
	}
	
	@Override
	public ByteBuffer get(ByteBuffer _key)
	{
		return m_node.get(_key);
	}

	@Override
	public NodeAttributes getAll()
	{
		return m_node.getAll();
	}

	@Override
	public synchronized void put(ByteBuffer _key, ByteBuffer _value)
	{
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		d.put(_key,_value);
		
		cloneAndTransmit(d);
	}

	@Override
	public synchronized void putAll(NodeAttributes _map)
	{
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		d.putAll(_map);
		
		cloneAndTransmit(d);
	}

	@Override
	public synchronized void remove(ByteBuffer _key)
	{
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		d.remove(_key);
		
		cloneAndTransmit(d);
	}

	@Override
	public synchronized void removeAll(Set<ByteBuffer> _keys)
	{
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		d.removeAll(_keys);
		
		cloneAndTransmit(d);
	}

	@Override
	public synchronized void clearAttributes()
	{
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		d.clearAttributes();
		
		cloneAndTransmit(d);
	}
	
	public synchronized void cloneAndTransmit(NodeData<Node> _d)
	{
		OnMemoryForest f = (OnMemoryForest)m_node.getForest();
		Node clone = f.createNode(m_node.getID().update(),_d);
		transmit(m_node,clone);
		
		m_node = clone;
	}
	
	public synchronized void transmit(Node _orig,Node _edit)
	{
		OnMemoryForest f = (OnMemoryForest)m_node.getForest();
		OnMemoryNode clone = f.createNode(m_node.getID().update(),null);
		clone.replace(_edit);
		
		if(m_parent != null){
			m_parent.transmit(m_node,(OnMemoryNode)clone);
			return;
		}
	}
	
	private synchronized OnMemoryMonotonicTreeNode getCache(OnMemoryNode _node)
	{
		NodeID id = _node.getID();
		OnMemoryMonotonicTreeNode mono;
		synchronized(m_cache){
			mono = m_cache.get(id);
			if(mono == null){
				//cache not found . create it
				mono = new OnMemoryMonotonicTreeNode(_node,this);
			}
		}
		return mono;
	}
	
	@Override
	public synchronized Node getNode()
	{
		return m_node;
	}
	
	@Override
	public synchronized List<MonotonicTreeNode> getList()
	{
		//NodeのリストよりMonotonicTreeNodeのリストを作成する.
		NodeChildren<MonotonicTreeNode> res = new NodeChildrenImpl<MonotonicTreeNode>();
		for(Iterator<Node> it = m_node.getList().iterator();it.hasNext();){
			OnMemoryNode n = (OnMemoryNode)it.next();
			res.add(getCache(n));
		}
		
		return res.getList();
	}

	@Override
	public synchronized boolean add(MonotonicTreeNode _n)
	{
		OnMemoryMonotonicTreeNode mono = (OnMemoryMonotonicTreeNode)_n;
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		boolean ret = d.add(mono.m_node);
		if(ret){
			cloneAndTransmit(d);
		}
		
		return ret;
	}

	@Override
	public synchronized boolean addAll(NodeChildren<MonotonicTreeNode> _list)
	{
		//MotonicTreeNodeのリストからNodeのリストを作成する.
		NodeChildren<Node> c = new NodeChildrenImpl<Node>();
		for(Iterator<MonotonicTreeNode> it = _list.getList().iterator();it.hasNext();){
			OnMemoryMonotonicTreeNode mono = (OnMemoryMonotonicTreeNode)it.next();
			c.add(mono.m_node);
		}
		
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		boolean ret = d.addAll(c);
		if(ret){
			cloneAndTransmit(d);
		}
		
		return ret;
	}

	@Override
	public synchronized MonotonicTreeNode remove(int _index)
	{
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		OnMemoryNode n = (OnMemoryNode) d.remove(_index);
		if(n != null){
			cloneAndTransmit(d);
			return new OnMemoryMonotonicTreeNode((OnMemoryNode)n,null);
		}
		
		return null;
	}

	@Override
	public synchronized void clearChildren()
	{
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		d.clearChildren();
		
		cloneAndTransmit(d);
	}

	@Override
	public Map<ByteBuffer, ByteBuffer> asMap()
	{
		return m_node.asMap();
	}

	@Override
	public Set<ByteBuffer> getKeySet()
	{
		return m_node.getKeySet();
	}

	@Override
	public synchronized MonotonicTreeNode get(int _index)
	{
		OnMemoryNode n = (OnMemoryNode) m_node.get(_index);
		return getCache(n);
	}

	@Override
	public synchronized MonotonicTreeNode replace(MonotonicTreeNode _newChild)
	{
		OnMemoryMonotonicTreeNode mono = (OnMemoryMonotonicTreeNode)_newChild;
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		OnMemoryNode n = (OnMemoryNode) d.replace(mono.m_node);
		
		if(n != null){
			cloneAndTransmit(d);
			return new OnMemoryMonotonicTreeNode(n,null);
		}
		
		return null;
	}

	@Override
	public boolean contains(NodeID _id)
	{
		return m_node.contains(_id);
	}

	@Override
	public boolean swap(String _fid1,String _fid2)
	{
		return m_node.swap(_fid1,_fid2);
	}

	@Override
	public Set<String> getFamilyIDSet()
	{
		return m_node.getFamilyIDSet();
	}

	@Override
	public synchronized MonotonicTreeNode get(String _fid)
	{
		OnMemoryNode n = (OnMemoryNode) m_node.get(_fid);
		OnMemoryMonotonicTreeNode mono = getCache(n);
		
		return mono;
	}

	@Override
	public synchronized MonotonicTreeNode remove(String _fid)
	{
		NodeData<Node> d = new NodeData<Node>(m_node,m_node);
		OnMemoryNode n = (OnMemoryNode) d.remove(_fid);
		
		cloneAndTransmit(d);
		
		return new OnMemoryMonotonicTreeNode(n,null);
	}
}