# HG changeset patch # User Shoshi TAMAKI # Date 1359997474 -32400 # Node ID fb00d7b147c8c8df3cc2c50cd379b1a4483acad6 # Parent 449d67be088623013bd9fdf06470570bb0e306c1 added JungleTree service diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/DefaultJungle.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/DefaultJungle.java Tue Feb 05 02:04:34 2013 +0900 @@ -0,0 +1,49 @@ +package jp.ac.u_ryukyu.ie.cr.shoshi.jungle; + +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; + +import fj.data.List; + +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.ChangeList; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.Journal; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.NullJournal; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNode; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.operations.Operation; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.DefaultChangeSet; + +public class DefaultJungle implements Jungle +{ + private Journal journal; + private ConcurrentHashMap trees; + private String uuid; + + public DefaultJungle(String _uuid) + { + journal = new NullJournal(); + trees = new ConcurrentHashMap(); + uuid = _uuid; + } + + @Override + public JungleTree getTreeByName(String _name) + { + return trees.get(_name); + } + + @Override + public JungleTree createNewTree(String _name) + { + ChangeList list = new ChangeList(){ + @Override + public Iterator iterator() { + List nil = List.nil(); + return nil.iterator(); + } + }; + DefaultNode node = new DefaultNode(); + DefaultChangeSet set = new DefaultChangeSet(node,null,list,uuid,0); + DefaultJungleTree newTree = new DefaultJungleTree(set,uuid,journal.getWriter()); + return newTree; + } +} diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/DefaultJungleTree.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/DefaultJungleTree.java Tue Feb 05 02:04:34 2013 +0900 @@ -0,0 +1,118 @@ +package jp.ac.u_ryukyu.ie.cr.shoshi.jungle; + +import java.util.Iterator; + +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.Attributes; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.AttributesContainer; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.Children; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.Node; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.Parent; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.ChangeListWriter; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.ChangeSet; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNode; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.AtomicReservableReference; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.ClonableDefaultNode; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.DefaultChangeSet; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.DefaultJungleTreeEditor; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.DefaultTransactionManager; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.DefaultTraverser; +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; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.IterableConverter; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.IterableConverter.Converter; + +public class DefaultJungleTree implements JungleTree +{ + private final AtomicReservableReference repository; + private final String uuid; + private final ChangeListWriter writer; + + public DefaultJungleTree(DefaultChangeSet _set,String _uuid,ChangeListWriter _writer) + { + repository = new AtomicReservableReference(_set); + uuid = _uuid; + writer = _writer; + } + + @Override + public DefaultJungleTreeEditor getTreeEditor() + { + DefaultChangeSet tip = repository.get(); + DefaultTransactionManager txManager = new DefaultTransactionManager(writer,tip,repository,uuid); + DefaultNode root = tip.getRoot(); + return new DefaultJungleTreeEditor(root,txManager,new DefaultTraverser()); + } + + @Override + public Node getRootNode() + { + ChangeSet set = repository.get(); + return set.getRoot(); + } + + public static class NodeWrapper & AttributesContainer> implements Node + { + private final T wrap; + + public NodeWrapper(T _wrap) + { + wrap = _wrap; + } + + @Override + public Attributes getAttributes() + { + return wrap.getAttributes(); + } + + @Override + public Children getChildren() + { + Children children = wrap.getChildren(); + return new ChildrenWrapper(children); + } + + public static class ChildrenWrapper & AttributesContainer> implements Children + { + private Children wrap; + + public ChildrenWrapper(Children _wrap) + { + wrap = _wrap; + } + + @Override + public Iterator iterator() + { + Converter converter = new IterableConverter.Converter(){ + @Override + public Node conv(T _b){ + return new NodeWrapper(_b); + } + }; + + IterableConverter iterable = new IterableConverter(wrap,converter); + return iterable.iterator(); + } + + @Override + public Either at(int _pos) + { + Either either = wrap.at(_pos); + if(either.isA()){ + return DefaultEither.newA(either.a()); + } + T node = either.b(); + Node wrapper = new NodeWrapper(node); + return DefaultEither.newB(wrapper); + } + + @Override + public int size() + { + return wrap.size(); + } + } + } +} diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/JungleTreeEditor.java --- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/JungleTreeEditor.java Sun Feb 03 19:46:04 2013 +0900 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/JungleTreeEditor.java Tue Feb 05 02:04:34 2013 +0900 @@ -3,7 +3,8 @@ import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.Transaction; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.TreeEditor; -public interface JungleTreeEditor> extends TreeEditor , Transaction +public interface JungleTreeEditor> extends TreeEditor , Transaction { - + public String getID(); + public String getRevision(); } diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/persistent/ChangeListWriter.java --- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/persistent/ChangeListWriter.java Sun Feb 03 19:46:04 2013 +0900 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/persistent/ChangeListWriter.java Tue Feb 05 02:04:34 2013 +0900 @@ -2,5 +2,5 @@ public interface ChangeListWriter { - public Result write(); + public Result write(ChangeList _operations); } diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/persistent/NullJournal.java --- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/persistent/NullJournal.java Sun Feb 03 19:46:04 2013 +0900 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/persistent/NullJournal.java Tue Feb 05 02:04:34 2013 +0900 @@ -20,7 +20,7 @@ private static class NullChangeListWriter implements ChangeListWriter { @Override - public Result write() + public Result write(ChangeList _operations) { return Result.SUCCESS; } diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/TraversableNodeWrapper.java --- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/TraversableNodeWrapper.java Sun Feb 03 19:46:04 2013 +0900 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/TraversableNodeWrapper.java Tue Feb 05 02:04:34 2013 +0900 @@ -3,6 +3,7 @@ import java.util.Iterator; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.Children; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.Parent; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.EditableNode; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.TraversableNode; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.DefaultEither; @@ -10,7 +11,7 @@ import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Error; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.IterableConverter; -public class TraversableNodeWrapper> +public class TraversableNodeWrapper> implements TraversableNode> { private final T wrap; diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/AtomicReservableReference.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/AtomicReservableReference.java Tue Feb 05 02:04:34 2013 +0900 @@ -0,0 +1,90 @@ +package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +public class AtomicReservableReference +{ + public static void main(String _args[]) + { + String hoge = "hoge"; + String fuga = "fuga"; + AtomicReservableReference arr = new AtomicReservableReference(hoge); + AtomicReservableReference.Reservation r1 = arr.makeReservation(hoge,fuga); + AtomicReservableReference.Reservation r2 = arr.makeReservation(hoge,fuga); + + System.out.println(arr.get()); + r1.confirm(); + System.out.println(arr.get()); + } + + private AtomicReference reservation; + private AtomicBoolean flagReservation; + + public AtomicReservableReference(V _ref) + { + reservation = new AtomicReference(new Reservation(_ref,null,true)); + flagReservation = new AtomicBoolean(false); + } + + public Reservation makeReservation(V _expect,V _update) + { + if(flagReservation.compareAndSet(false,true)){ + V value = get(); + if(value == _expect){ + Reservation expect = reservation.get(); + return new Reservation(_update,expect,false); + } + flagReservation.set(false); + } + + return null; + } + + public void set(V _value) + { + reservation.set(new Reservation(_value,null,true)); + } + + public V get() + { + Reservation r = reservation.get(); + return r.get(); + } + + public class Reservation + { + public final Reservation expect; + public final AtomicReference ref; + public final AtomicBoolean flagConfirmed; + + public Reservation(V _object,Reservation _expect,boolean _confirmed) + { + expect = _expect; + ref = new AtomicReference(_object); + flagConfirmed = new AtomicBoolean(_confirmed); + } + + public V get() + { + return ref.get(); + } + + public void confirm() + { + if(flagConfirmed.compareAndSet(false,true)){ + if(reservation.compareAndSet(expect,this) == false){ + throw new IllegalStateException("foo!"); + } + flagReservation.set(false); + } + } + + public void cancel() + { + if(flagConfirmed.compareAndSet(false,true)){ + flagReservation.set(true); + } + } + } +} diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/ClonableDefaultNode.java --- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/ClonableDefaultNode.java Sun Feb 03 19:46:04 2013 +0900 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/ClonableDefaultNode.java Tue Feb 05 02:04:34 2013 +0900 @@ -7,6 +7,11 @@ { private final DefaultNode wrap; + public ClonableDefaultNode() + { + this(new DefaultNode()); + } + public ClonableDefaultNode(DefaultNode _wrap) { wrap = _wrap; diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultChangeSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultChangeSet.java Tue Feb 05 02:04:34 2013 +0900 @@ -0,0 +1,63 @@ +package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction; + +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.Node; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.ChangeList; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.ChangeSet; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNode; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.DefaultLogger; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.operations.Operation; + +public class DefaultChangeSet implements ChangeSet +{ + private final DefaultNode root; + private final ChangeSet previous; + private final ChangeList changeList; + private final String uuid; + private final long revision; + + public DefaultChangeSet(DefaultNode _node,ChangeSet _prev,ChangeList _log,String _uuid,long _revision) + { + root = _node; + previous = _prev; + changeList = _log; + uuid = _uuid; + revision = _revision; + } + + @Override + public DefaultNode getRoot() + { + return root; + } + + @Override + public ChangeSet prev() + { + return previous; + } + + @Override + public ChangeList getChangeList() + { + return changeList; + } + + @Override + public String uuid() + { + return uuid; + } + + @Override + public long revision() + { + return revision; + } + + @Override + public Iterable getOperations() + { + return changeList; + } + +} diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultJungleTreeEditor.java --- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultJungleTreeEditor.java Sun Feb 03 19:46:04 2013 +0900 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultJungleTreeEditor.java Tue Feb 05 02:04:34 2013 +0900 @@ -103,18 +103,32 @@ } @Override - public Either success() + public Either success() { LoggingNode loggingNode = editor.getRootNode(); Logger log = loggingNode.getLogger(); DefaultNode newRoot = loggingNode.getWrapper().getWrapped(); - Either either = txManager.commit(newRoot,log); + Either either = txManager.commit(newRoot,log); if(either.isA()){ return DefaultEither.newA(either.a()); } - return DefaultEither.newB(either.b()); + TransactionManager newTxManager = either.b(); + DefaultJungleTreeEditor newTreeEditor = new DefaultJungleTreeEditor(newRoot,newTxManager,traverser); + + return DefaultEither.newB(newTreeEditor); } + @Override + public String getID() + { + return txManager.getUUID(); + } + + @Override + public String getRevision() + { + return Long.toString(txManager.getRevision()); + } } diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTransactionManager.java --- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTransactionManager.java Sun Feb 03 19:46:04 2013 +0900 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTransactionManager.java Tue Feb 05 02:04:34 2013 +0900 @@ -1,17 +1,76 @@ package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction; +import java.util.Iterator; +import java.util.concurrent.atomic.AtomicReference; + import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTree; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.ChangeList; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.ChangeListWriter; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.persistent.Result; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.ChangeSet; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNode; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.DefaultLogger; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.Logger; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.operations.Operation; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.AtomicReservableReference.Reservation; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.DefaultEither; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.DefaultError; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Either; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Error; public class DefaultTransactionManager implements TransactionManager { + private final AtomicReservableReference repository; + private final DefaultChangeSet tip; + private final ChangeListWriter writer; + private final String uuid; + + public DefaultTransactionManager(ChangeListWriter _writer,DefaultChangeSet _changeSet, + AtomicReservableReference _repository,String _uuid) + { + repository = _repository; + tip = _changeSet; + writer = _writer; + uuid = _uuid; + } + @Override - public Either commit(DefaultNode _newRoot, Logger _log) + public Either commit(DefaultNode _newRoot,final Logger _log) { - return null; + long currentRevision = tip.revision(); + long nextRevision = currentRevision + 1; + + ChangeList list = new ChangeList(){ + @Override + public Iterator iterator(){ + return _log.iterator(); + } + }; + + DefaultChangeSet changeSet = new DefaultChangeSet(_newRoot,tip,list,uuid,nextRevision); + Reservation reservation = repository.makeReservation(tip,changeSet); + if(reservation == null){ + return DefaultEither.newA((Error)new DefaultError()); + } + Result r = writer.write(list); + if(r == Result.SUCCESS){ + reservation.confirm(); + TransactionManager txManager = new DefaultTransactionManager(writer,changeSet,repository,uuid); + return DefaultEither.newB(txManager); + } + + return DefaultEither.newA((Error)new DefaultError()); } + @Override + public String getUUID() + { + return uuid; + } + + @Override + public long getRevision() + { + return tip.revision(); + } } diff -r 449d67be0886 -r fb00d7b147c8 src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/TransactionManager.java --- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/TransactionManager.java Sun Feb 03 19:46:04 2013 +0900 +++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/TransactionManager.java Tue Feb 05 02:04:34 2013 +0900 @@ -1,6 +1,5 @@ package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction; -import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTree; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNode; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.Logger; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Either; @@ -8,5 +7,7 @@ public interface TransactionManager { - public Either commit(DefaultNode _newRoot,Logger _log); + public Either commit(DefaultNode _newRoot,Logger _log); + public String getUUID(); + public long getRevision(); } diff -r 449d67be0886 -r fb00d7b147c8 src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/impl/treeeditor/DefaultTreeEditorTest.java --- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/impl/treeeditor/DefaultTreeEditorTest.java Sun Feb 03 19:46:04 2013 +0900 +++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/impl/treeeditor/DefaultTreeEditorTest.java Tue Feb 05 02:04:34 2013 +0900 @@ -5,9 +5,13 @@ import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNode; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNodePath; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultTreeEditor; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TraversableNodeWrapper; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.AppendChildAt; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.tests.util.TestUtil; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.ClonableDefaultNode; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.DefaultEvaluator; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.DefaultTraverser; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser.Traversal; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Either; import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Error; import junit.framework.Assert; @@ -24,6 +28,49 @@ public void testEdittingDoesNotEffectToOtherTree() { + ClonableDefaultNode root = TestUtil.createMockTree(3); + DefaultTreeEditor editor = new DefaultTreeEditor(root,new DefaultTraverser()); + DefaultNodePath path = new DefaultNodePath().add(0).add(2); + + ClonableDefaultNode oldRoot = editor.getRootNode(); + + DefaultTreeEditor currentEditor = editor; + String key = "path"; + + for(DefaultNodePath part : path.inits()){ + ByteBuffer value = ByteBuffer.wrap(part.toString().getBytes()); + Either> either = currentEditor.putAttribute(part,key,value); + if(either.isA()){ + Assert.fail(); + } + currentEditor = either.b(); + } + + ClonableDefaultNode newRoot = currentEditor.getRootNode(); + + DefaultTraverser traverser = new DefaultTraverser(); + for(DefaultNodePath part : path.inits()){ + Either>> either = traverser.traverse(new TraversableNodeWrapper(newRoot),new DefaultEvaluator(part)); + if(either.isA()){ + Assert.fail(); + } + ClonableDefaultNode target = either.b().destination().getWrapped(); + String expected = part.toString(); + String actual = new String(target.getAttributes().get(key).array()); + + Assert.assertEquals(expected,actual); + } + + for(DefaultNodePath part : path.inits()){ + Either>> either = traverser.traverse(new TraversableNodeWrapper(oldRoot),new DefaultEvaluator(part)); + if(either.isA()){ + Assert.fail(); + } + ClonableDefaultNode target = either.b().destination().getWrapped(); + ByteBuffer actual = target.getAttributes().get(key); + + Assert.assertNull(actual); + } } @@ -69,6 +116,8 @@ DefaultTreeEditor instance = instance(); DefaultNodePath path = new DefaultNodePath(); + ClonableDefaultNode old = instance.getRootNode(); + String key = "KEY"; ByteBuffer value = ByteBuffer.wrap(key.getBytes()); diff -r 449d67be0886 -r fb00d7b147c8 src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/tests/util/TestUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/tests/util/TestUtil.java Tue Feb 05 02:04:34 2013 +0900 @@ -0,0 +1,40 @@ +package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.tests.util; + +import java.nio.ByteBuffer; + +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.NodePath; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNodePath; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.ClonableDefaultNode; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Either; +import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Error; + +public class TestUtil +{ + public static ClonableDefaultNode createMockTree(int _maxDepth) + { + return _createMockTree(1,_maxDepth,new DefaultNodePath()); + } + + public static ClonableDefaultNode _createMockTree(int _currentDepth,int _maxDepth,NodePath _path) + { + ClonableDefaultNode parent = new ClonableDefaultNode(); + Either either = parent.getAttributes().put("KEY",ByteBuffer.wrap(_path.toString().getBytes())); + if(either.isA()){ + return null; + } + parent = either.b(); + + if(_currentDepth != _maxDepth){ + for(int i = 0;i <= _currentDepth;i ++){ + ClonableDefaultNode ch = _createMockTree(_currentDepth + 1,_maxDepth,_path.add(i)); + either = parent.getChildren().addNewChildAt(i,ch); + if(either.isA()){ + return null; + } + parent = either.b(); + } + } + + return parent; + } +}