view src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/DefaultTreeEditor.java @ 31:418088ca2b30

added Generics parameters to EditableNode framework
author Shoshi TAMAKI
date Wed, 16 Jan 2013 03:23:57 +0900
parents 53090dc21231
children dd7776c8b6d5
line wrap: on
line source

package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl;

import java.nio.ByteBuffer;
import java.util.Iterator;

import fj.data.List;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.ChangeListWriter;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.NodePath;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.TraversableTree;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.TreeEditor;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.TreeEditorError;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.Logger;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.LoggingNode;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.AppendChildAt;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.DeleteAttribute;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.DeleteChildAt;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.EditableNode;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.NodeEditor;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.PutAttribute;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.DefaultEvaluator;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.Direction;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.Traversal;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.Traverser;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.DefaultEither;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Either;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Error;

public class DefaultTreeEditor implements TreeEditor
{
	private final DefaultChangeSet tip;
	private final TraverserProvider tProvider;
	
	public DefaultTreeEditor(DefaultChangeSet _tip,ChangeListWriter _writer,TraverserProvider _tProvider)
	{
		tip = _tip;
		tProvider = _tProvider;
	}

	@Override
	public TraversableTree getTree()
	{
		return null;
	}
	
	@Override
	public Either<Error,TreeEditor> appendChild(NodePath _path,int _pos)
	{
		return edit(_path,new AppendChildAt(_pos));
	}
	

	@Override
	public Either<Error,TreeEditor> deleteChild(NodePath _path,int _pos)
	{
		return edit(_path,new DeleteChildAt(_pos));
	}

	@Override
	public Either<Error,TreeEditor> putAttribute(NodePath _path, String _key,ByteBuffer _value)
	{
		return edit(_path,new PutAttribute(_key,_value));
	}

	@Override
	public Either<Error,TreeEditor> deleteAttribute(NodePath _path, String _key)
	{
		return edit(_path,new DeleteAttribute(_key));
	}

	@Override
	public boolean success()
	{
		return false;
	}

	@Override
	public Either<Error,TreeEditor> edit(NodePath _path,NodeEditor _editor)
	{
		DefaultTree tree = tip.getTree();
		DefaultNode root = tree.getRoot();
		Traverser<DefaultNode> traverser = tProvider.newTraverser();
		DefaultEvaluator<DefaultNode> e = new DefaultEvaluator<DefaultNode>(_path);
		
		Either<Error,Traversal<DefaultNode>> either = traverser.traverse(root,e);
		if(either.isA()){
			return DefaultEither.newA(either.a());
		}
		
		Traversal<DefaultNode> t = either.b();
		Either<Error,TreeEditor> ret = clone(t,_editor);
		
		return ret;
	}
	
	private Either<Error,TreeEditor> clone(Traversal<DefaultNode> _t,NodeEditor _editor)
	{
		// copying nodes from bottom to root
		
		List<Direction<DefaultNode>> path = List.nil();
		for(Direction<DefaultNode> direction : _t){
			path = path.cons(direction);
		}
		
		// target
		Direction<DefaultNode> targetDirection = path.head();
		Either<Error,LoggingNode<DefaultNode>> either = _editor.edit(new LoggingNode<DefaultNode>(targetDirection.getTarget()));
		if(either.isA()){
			return DefaultEither.newA(either.a());
		}
		
		LoggingNode<DefaultNode> loggingNode = either.b();
		Logger logger = loggingNode.getLogger();
		DefaultNode newNode = (DefaultNode)loggingNode.getWrapper();
		
		// top
		int pos = targetDirection.getPosition();
		DefaultNode child = newNode;
		for(Direction<DefaultNode> parentDirection : path.tail()){
			DefaultNode parent = parentDirection.getTarget();
			DefaultChildren chs = parent.getChildren();
			Either<Error,DefaultNode> ret = chs.replaceNode(child,pos);
			if(ret.isA()){
				return DefaultEither.newA(ret.a());
			}
			
			DefaultNode newParent = ret.b();
			child = newParent;
			pos = parentDirection.getPosition();
		}
		
		DefaultNode newRoot = child;
		TreeEditor newEditor = new DefaultModifiedTreeEditor(logger);
		return DefaultEither.newB(newEditor);
	}
	
	protected Either<Error,TreeEditor> newEditor(Logger _logger,DefaultNode _newRoot)
	{
		List<Logger> logs = List.list(_logger);
		TreeEditor newEditor = null;
		return DefaultEither.newB(_theB);
	}
}