view src/treecms/proto/cassandra/v1/CassEditor.java @ 51:d4709911e0ed

moved old Cassandra Monotonic-Tree implementation from "cassandra" to "cassandra.v1"
author shoshi
date Fri, 11 Feb 2011 15:07:57 +0900
parents src/treecms/proto/cassandra/CassEditor.java@a72718a0bccf
children
line wrap: on
line source

package treecms.proto.cassandra.v1;

import treecms.proto.api.Editor;
import java.util.List;

import java.util.LinkedList;

import treecms.proto.api.Browser;
import treecms.proto.api.Node;
import treecms.proto.api.NodeID;
import treecms.proto.marge.Marger;
import treecms.proto.marge.ReplaceMarger;

public class CassEditor implements Editor
{
	private Node m_local;
	private Node m_remote;
	
	private Browser m_browser;
	
	public CassEditor(Browser _browser)
	{
		m_browser = _browser;
		update();
	}
	
	public void copyNode(Node _from,Node _to)
	{
		_to.setClassName(_from.getClassName());
		_to.setTitle(_from.getTitle());
		
		for(String _key : _from.getAttributeKeys()){
			_to.setAttribute(_key,_from.getAttribute(_key));
		}
		
		_to.addChildren(_from.getChildren());
	}
	
	@Override
	public boolean check()
	{
		NodeID remoteID = m_remote.getID();
		if(remoteID.equals(remoteID.getTip())){
			return false;
		}
		return true;
	}
	
	public boolean commit(boolean _force)
	{
		if(_force || !check()){
			Node target = m_remote.cloneNode();
			target.clearChildren();
			copyNode(m_local,target);
			return true;
		}
		
		return false;
	}
	
	public void merge()
	{
		Marger marger = new ReplaceMarger();
		m_local = marger.merge(m_remote,m_local);
	}
	
	public void discard()
	{
		copyNode(m_remote,m_local);
	}

	@Override
	public Node useContents()
	{
		return m_local;
	}

	@Override
	public void login(String user, String pass)
	{
	}

	@Override
	public void logout()
	{
	}

	@Override
	public Node edit(Node _target)
	{
		LinkedList<Node> path = findPath(m_local,_target);
		if(path.isEmpty()){
			return null;
		}
		
		LinkedList<Node> change = new LinkedList<Node>();
		Node root = path.poll().cloneNode();
		change.add(root);
		cloneTree(path,root,change);
		
		m_local = root;
		
		Node clone = change.peekLast();
		return clone;
	}
	
	private void cloneTree(LinkedList<Node> _path,Node _parent,LinkedList<Node> _change)
	{
		List<Node> children = _parent.getChildren();
		Node target = _path.poll();
		if(target == null){
			return;
		}
		for(int i = 0;i < children.size();i ++){
			Node _child = children.get(i);
			if(_child.getID().isFamily(target.getID())){
				//clone node
				Node clone = _child.cloneNode();
				_change.add(clone);
				
				//remove old node from clonedTree
				_parent.replace(_child,clone);
				
				cloneTree(_path,clone,_change);
				break;
			}
		}
	}
	
	private LinkedList<Node> findPath(Node _root,Node _child)
	{
		LinkedList<Node> list = new LinkedList<Node>();
		if(findPath(_root,_child,list)){
			list.addFirst(_root);
		}
		return list;
	}
	
	private boolean findPath(Node _root,Node _child,LinkedList<Node> _list)
	{
		if(_root.getID().isFamily(_child.getID())){
			return true;
		}
		
		for(Node child : _root.getChildren()){
			if(findPath(child,_child,_list)){
				_list.addFirst(child);
				return true;
			}
		}
		return false;
	}

	@Override
	public Node getUncommited()
	{
		return m_local;
	}

	@Override
	public boolean update()
	{
		m_remote = m_browser.useContents();
		m_local = m_remote.createNode();
		
		copyNode(m_remote,m_local);
		return true;
	}
}