view src/treecms/tree/memory/OnMemoryTree.java @ 0:7ecb9273581d

hg init
author shoshi
date Wed, 16 Feb 2011 14:27:35 +0900
parents
children
line wrap: on
line source

package treecms.tree.memory;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import treecms.api.Node;
import treecms.api.NodeID;
import treecms.api.Tree;
import treecms.tree.id.RandomNodeID;

public class OnMemoryTree implements Tree
{
	public OnMemoryNode m_root;
	
	public static void main(String _args[])
	{
		OnMemoryTree tree = new OnMemoryTree();
		
		Node root = tree.useContents();
		Node child1 = root.createNode();
		child1.setAttribute("hogehoge","fugafuga".getBytes());
		Node newRoot = root.addChild(child1);
	}
	
	public OnMemoryTree()
	{
		m_root = createNode(null);
	}
	
	@Override
	public Node useContents()
	{
		return m_root;
	}
	
	public synchronized OnMemoryNode clonetree(OnMemoryNode _target,NodeData _newData)
	{
		LinkedList<OnMemoryNode> path  = findAndClone(m_root,_target,_newData);
		
		if(path == null){
			return null;
		}
		
		//replace.
		m_root = path.peekFirst();
		return path.peekLast();
	}
	
	public LinkedList<OnMemoryNode> findAndClone(OnMemoryNode _parent,OnMemoryNode _target,NodeData _newData)
	{
		if(_parent.getID().isFamily(_target.getID())){
			//find.
			OnMemoryNode clone = cloneNode(_target,_newData);
			LinkedList<OnMemoryNode> path = new LinkedList<OnMemoryNode>();
			path.add(clone);
			return path;
		}
		
		for(Node child : _parent.getChildren()){
			LinkedList<OnMemoryNode> path = findAndClone((OnMemoryNode)child,_target,_newData);
			if(path != null){
				OnMemoryNode clone = cloneNode(_parent,null);
				clone.removeChild(child);
				clone.addChild(path.peekFirst());
				path.addFirst(clone);
				return path;
			}
		}
		
		return null;
	}
	
	public OnMemoryNode cloneNode(OnMemoryNode _target,NodeData _newData)
	{
		OnMemoryNode node = createNode(_target.getID().update());
		
		if(_newData != null){
			node.m_attrs.putAll(_newData.m_attrs);
			node.m_children.addAll(_newData.m_children);
			return node;
		}
		
		node.m_attrs.putAll(_target.m_attrs);
		node.m_children.addAll(_target.m_children);
		return node;
	}
	
	public NodeData extractData(OnMemoryNode _target)
	{
		NodeData data = new NodeData();
		data.m_attrs.putAll(_target.getAttributeMap());
		data.m_children.addAll(_target.getChildren());
		return data;
	}
	
	public OnMemoryNode createNode(NodeID _id)
	{
		OnMemoryNode newNode;
		if(_id != null){
			newNode = new OnMemoryNode(_id,this);
		}else{
			newNode = new OnMemoryNode(createID(),this);
		}
		return newNode;
	}
	
	public NodeID createID()
	{
		return new RandomNodeIDImpl(null);
	}
	
	class NodeData
	{
		Tree m_tree;
		Set<Node> m_children;
		Map<String,byte[]> m_attrs;
		
		public NodeData()
		{
			m_tree = null;
			m_children = new HashSet<Node>();
			m_attrs = new HashMap<String,byte[]>();
		}
	}
	
	class RandomNodeIDImpl extends RandomNodeID
	{
		private String m_uuid;
		private Long m_version;
		
		public RandomNodeIDImpl(String _uuid)
		{
			if(_uuid != null){
				m_uuid = _uuid;
			}else{
				m_uuid = UUID.randomUUID().toString();
			}
			
			m_version = (new Random()).nextLong();
		}
		
		@Override
		public NodeID create()
		{
			return new RandomNodeIDImpl(null);
		}

		@Override
		public String getUUID()
		{
			return m_uuid;
		}

		@Override
		public String getVersion()
		{
			return Long.toHexString(m_version);
		}
		
		@Override
		public String toString()
		{
			return m_uuid + "@" + Long.toHexString(m_version);
		}

		@Override
		public NodeID update()
		{
			RandomNodeIDImpl newID = new RandomNodeIDImpl(m_uuid);
			return newID;
		}
	}
}