view src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/DefaultTreeEditor.java @ 38:cb9fabaedfd4

added tests and changed testing provider to junit47
author Shoshi TAMAKI
date Mon, 28 Jan 2013 18:52:52 +0900
parents 35e327577b58
children e3a507fd57a4
line wrap: on
line source

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

import java.nio.ByteBuffer;
import fj.data.List;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.NodePath;
import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.TreeEditor;
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.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<T extends ClonableNode<T>>
	implements TreeEditor<DefaultTreeEditor<T>>
{
	private final T root;
	private final Traverser traverser;
	
	public DefaultTreeEditor(T _root,Traverser _traverser)
	{
		root = _root;
		traverser = _traverser;
	}
	
	public T getRootNode()
	{
		return root;
	}

	@Override
	public Either<Error,DefaultTreeEditor<T>> appendChild(NodePath _path,int _pos)
	{
		return edit(_path,new AppendChildAt(_pos));
	}

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

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

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

	@Override
	public Either<Error,DefaultTreeEditor<T>> edit(NodePath _path,NodeEditor _editor)
	{
		DefaultEvaluator e = new DefaultEvaluator(_path);
		TraversableNodeWrapper<T> wrap = new TraversableNodeWrapper<T>(root);
		Either<Error, Traversal<TraversableNodeWrapper<T>>> either = traverser.traverse(wrap,e);
		
		if(either.isA()){
			return DefaultEither.newA(either.a());
		}
		
		Traversal<TraversableNodeWrapper<T>> t = either.b();
		Either<Error,DefaultTreeEditor<T>> ret = clone(t,_editor);
		
		return ret;
	}
	
	private Either<Error,DefaultTreeEditor<T>> clone(Traversal<TraversableNodeWrapper<T>> _t,NodeEditor _editor)
	{
		// copying nodes from bottom to root
		
		List<Direction<TraversableNodeWrapper<T>>> path = List.nil();
		for(Direction<TraversableNodeWrapper<T>> direction : _t){
			path = path.cons(direction);
		}
		
		// target
		Direction<TraversableNodeWrapper<T>> targetDirection = path.head();
		T target = targetDirection.getTarget().getWrapped();
		Either<Error,T> either = _editor.edit(target);
		if(either.isA()){
			return DefaultEither.newA(either.a());
		}
		
		T newNode = either.b();
		
		// top
		int pos = targetDirection.getPosition();
		T child = newNode;
		for(Direction<TraversableNodeWrapper<T>> parentDirection : path.tail()){
			TraversableNodeWrapper<T> parent = parentDirection.getTarget();
			ClonableChildren<T> chs = parent.getWrapped().getChildren();
			
			Either<Error,T> ret = chs.replaceNode(pos,child);
			if(ret.isA()){
				return DefaultEither.newA(ret.a());
			}
			
			T newParent = ret.b();
			child = newParent;
			pos = parentDirection.getPosition();
		}
		
		T newRoot = child;
		DefaultTreeEditor<T> newEditor = new DefaultTreeEditor<T>(newRoot,traverser);
		return DefaultEither.newB(newEditor);
	}
}