changeset 298:1f132728ae40

implement replaceNode and putAttribute for RedBlackTree
author tatsuki
date Thu, 05 Jan 2017 21:27:46 +0900
parents 1f929fe9c153
children 67ff36237722
files src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/Default/DefaultTreeNodeChildren.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/redBlackTree/ColorlessTreeNode.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/redBlackTree/RedBlackTreeNodeAttribute.java src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/redBlackTree/RedBlackTreeNodeChildren.java src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/core/treeeditor/RedBlack/RedBlackTreeEditorAttributeTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/core/treeeditor/RedBlack/RedBlackTreeEditorNodeTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/core/treeeditor/RedBlack/RedBlackTreeEditorTest.java
diffstat 7 files changed, 212 insertions(+), 155 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/Default/DefaultTreeNodeChildren.java	Thu Jan 05 09:49:20 2017 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/Default/DefaultTreeNodeChildren.java	Thu Jan 05 21:27:46 2017 +0900
@@ -81,10 +81,10 @@
         return DefaultEither.newB(newNode);
     }
 
-
+    //まだ実装していない もともと赤黒木の編集用
     @Override
     public Either<Error, TreeNode> matchingChildDeleteAt(String key, ByteBuffer value) {
-        return null; // 未使用
+        return null;
     }
 
     @Override
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/redBlackTree/ColorlessTreeNode.java	Thu Jan 05 09:49:20 2017 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/redBlackTree/ColorlessTreeNode.java	Thu Jan 05 21:27:46 2017 +0900
@@ -99,7 +99,7 @@
 
     @Override
     public RedBlackTreeNodeAttribute getAttributes() {
-        return new RedBlackTreeNodeAttribute(left(), right(), getAttrs(), key(), value());
+        return new RedBlackTreeNodeAttribute(this, getAttrs(), key(), value());
     }
 
     @Test
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/redBlackTree/RedBlackTreeNodeAttribute.java	Thu Jan 05 09:49:20 2017 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/redBlackTree/RedBlackTreeNodeAttribute.java	Thu Jan 05 21:27:46 2017 +0900
@@ -1,8 +1,10 @@
 package jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.redBlackTree;
 
 import jp.ac.u_ryukyu.ie.cr.jungle.data.treemap.TreeMap;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.trasnformer.NodeEditorError;
 import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
 import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNodeAttributes;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.DefaultEither;
 import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
 import jp.ac.u_ryukyu.ie.cr.jungle.util.Error.Error;
 
@@ -19,11 +21,14 @@
     private final TreeMap<String, ByteBuffer> attrs;
     private final String balanceKey;
     private final ByteBuffer value;
+    private final ColorlessTreeNode node;
 
-    public RedBlackTreeNodeAttribute(TreeNode leftChild, TreeNode rightChild, TreeMap<String, ByteBuffer> attrs, String balanceKey, ByteBuffer value) {
+
+    public RedBlackTreeNodeAttribute(ColorlessTreeNode node, TreeMap<String, ByteBuffer> attrs, String balanceKey, ByteBuffer value) {
         this.attrs = attrs;
         this.balanceKey = balanceKey;
         this.value = value;
+        this.node = node;
     }
 
     @Override
@@ -32,8 +37,14 @@
     }
 
     @Override
-    public Either<Error, TreeNode> put(String key, ByteBuffer value) {
-        return null;
+    public Either<Error, TreeNode> put(String key, ByteBuffer insertValue) {
+        if (key == null || insertValue == null) {
+            return DefaultEither.newA(NodeEditorError.NULL_VALUE_NOT_ALLOWED);
+        }
+
+        TreeMap<String, ByteBuffer> newMap = attrs.put(key, insertValue);
+        TreeNode newNode = node.createNode(newMap,balanceKey,value,node.left(),node.right());
+        return DefaultEither.newB(newNode);
     }
 
     @Override
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/redBlackTree/RedBlackTreeNodeChildren.java	Thu Jan 05 09:49:20 2017 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/transaction/node/redBlackTree/RedBlackTreeNodeChildren.java	Thu Jan 05 21:27:46 2017 +0900
@@ -1,6 +1,7 @@
 package jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.redBlackTree;
 
-import jp.ac.u_ryukyu.ie.cr.jungle.data.treemap.*;
+import jp.ac.u_ryukyu.ie.cr.jungle.data.treemap.Rotate;
+import jp.ac.u_ryukyu.ie.cr.jungle.data.treemap.TreeMap;
 import jp.ac.u_ryukyu.ie.cr.jungle.store.trasnformer.NodeEditorError;
 import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
 import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNodeChildren;
@@ -51,7 +52,7 @@
 
     @Override
     public Either<Error, TreeNode> addNewChildAndPutAttribtue(int pos, String key, ByteBuffer value) {
-        ColorlessTreeNode newNode = node.addNewChild(key,value);
+        ColorlessTreeNode newNode = node.addNewChild(key, value);
         if (newNode.isRed()) {
             ColorlessTreeNode newRoot = new BlackTreeNode(newNode);
             return DefaultEither.newB(newRoot);
@@ -69,7 +70,7 @@
         ColorlessTreeNode root = newNode.getNode();
         if (root.empty())
             return DefaultEither.newB(new EmptyTreeNode());
-        ColorlessTreeNode newRoot = new BlackTreeNode(root.getAttrs(),root.key(), root.value(), root.left(), root.right());
+        ColorlessTreeNode newRoot = new BlackTreeNode(root.getAttrs(), root.key(), root.value(), root.left(), root.right());
         return DefaultEither.newB(newRoot);
     }
 
@@ -81,9 +82,18 @@
 
     @Override
     public Either<Error, TreeNode> replaceNode(int pos, TreeNode replacement) {
-        return null;
-    } //使わない
+        if (!boundaryCheck(pos)) {
+            return DefaultEither.newA(NodeEditorError.INDEX_OUT_OF_BOUNDS);
+        }
 
+        ColorlessTreeNode newNode;
+        if (pos == 0) { //左のノードを入れ替える場合
+            newNode = node.createNode(attrs,node.key(),node.value(),(ColorlessTreeNode) replacement,node.right());
+        } else {
+            newNode = node.createNode(attrs,node.key(),node.value(),node.left(),(ColorlessTreeNode) replacement);
+        }
+        return DefaultEither.newB(newNode);
+    }
     @Override
     public Either<Error, TreeNode> moveChild(int pos, String move) {
         return null;
@@ -120,6 +130,26 @@
 
     @Override
     public Iterator<TreeNode> iterator() {
-        return null;
+        return new Iterator<TreeNode>() {
+
+            ColorlessTreeNode next = !node.left().empty() ? node.left() : node.right();
+
+            @Override
+            public boolean hasNext() {
+                return !next.empty();
+            }
+
+            @Override
+            public TreeNode next() {
+                TreeNode current = next;
+                if (next.equals(node.left())) {
+                    next = node.right();
+                    return current;
+                }
+                next = new EmptyTreeNode();
+                return current;
+            }
+
+        };
     }
-}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/core/treeeditor/RedBlack/RedBlackTreeEditorAttributeTest.java	Thu Jan 05 21:27:46 2017 +0900
@@ -0,0 +1,61 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.core.treeeditor.RedBlack;
+
+import jp.ac.u_ryukyu.ie.cr.jungle.DefaultJungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.Jungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.DefaultNodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.NodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.editor.jungleTreeEditor.JungleTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
+import jp.ac.u_ryukyu.ie.cr.jungle.traverser.DefaultTraverser;
+import jp.ac.u_ryukyu.ie.cr.jungle.tree.JungleTree;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Error.Error;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Created by e115731 on 2017/01/05.
+ */
+public class RedBlackTreeEditorAttributeTest {
+    @Test
+    public void RedBlackTreeEditorAttribute(){
+        String balanceKey = "balanceKey";
+        String key = "key";
+        Jungle jungle = new DefaultJungle(null, "hogehoge", new DefaultTraverser());
+        JungleTree tree = jungle.createNewRedBlackTree("TreeName", "balanceKey");
+        NodePath path = new DefaultNodePath();
+
+        for (int count = 1; count <= 10; count++) { //とりあえず木構造の構築
+            JungleTreeEditor editor = tree.getJungleTreeEditor();
+            ByteBuffer value = ByteBuffer.wrap(("value" + count).getBytes());
+            Either<Error, JungleTreeEditor> either = editor.addNewChildAndPutAttribute(path, 0, balanceKey, value);
+            Assert.assertFalse(either.isA());
+            editor = either.b();
+            either = editor.success();
+            Assert.assertFalse(either.isA());
+        }
+
+        JungleTreeEditor editor = tree.getJungleTreeEditor();
+        path = path.add(1);
+        ByteBuffer value = ByteBuffer.wrap(path.toString().getBytes());
+        Either<Error, JungleTreeEditor> either = editor.putAttribute(path, key, value);
+        Assert.assertFalse(either.isA()); //AttributeのPutが成功したかどうか
+        editor = either.b();
+        either = editor.success();
+        Assert.assertFalse(either.isA());
+
+        JungleTree oldTree = tree.getOldTree(tree.revision() - 1).b();
+        TreeNode oldRoot = oldTree.getRootNode();
+        TreeNode newRoot = tree.getRootNode();
+        Assert.assertNotEquals(newRoot,oldRoot);// とりあえずルートがちゃんと入れ替えられているかを調べる
+        TreeNode editedNode = tree.getNodeOfPath(path).b();
+        TreeNode editedOldNode = oldTree.getNodeOfPath(path).b();
+        String putValue = editedNode.getAttributes().getString(key);//編集したノードからputしたAttributeを取得
+        Assert.assertEquals(putValue,path.toString());
+        ByteBuffer nullValue = editedOldNode.getAttributes().get(key);//編集前のノードから値を取得 nullが取れる
+        Assert.assertNull(nullValue);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/core/treeeditor/RedBlack/RedBlackTreeEditorNodeTest.java	Thu Jan 05 21:27:46 2017 +0900
@@ -0,0 +1,97 @@
+package jp.ac.u_ryukyu.ie.cr.jungle.core.treeeditor.RedBlack;
+
+import jp.ac.u_ryukyu.ie.cr.jungle.DefaultJungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.Jungle;
+import jp.ac.u_ryukyu.ie.cr.jungle.core.Attributes;
+import jp.ac.u_ryukyu.ie.cr.jungle.query.JungleNodeIterator;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.DefaultNodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.NodePath;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.editor.jungleTreeEditor.JungleTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
+import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.redBlackTree.ColorlessTreeNode;
+import jp.ac.u_ryukyu.ie.cr.jungle.traverser.DefaultTraverser;
+import jp.ac.u_ryukyu.ie.cr.jungle.tree.JungleTree;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
+import jp.ac.u_ryukyu.ie.cr.jungle.util.Error.Error;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+public class RedBlackTreeEditorNodeTest {
+
+    int testCount = 1000;
+
+    @Test
+    public void RedBlackTreeEditorNode() {
+        String key = "balanceKey";
+        Jungle jungle = new DefaultJungle(null, "hogehoge", new DefaultTraverser());
+        JungleTree tree = jungle.createNewRedBlackTree("TreeName", "balanceKey");
+        NodePath path = new DefaultNodePath();
+
+        for (int count = 1; count <= testCount; count++) {
+            JungleTreeEditor editor = tree.getJungleTreeEditor();
+            ByteBuffer value = ByteBuffer.wrap(("value" + count).getBytes());
+            Either<Error, JungleTreeEditor> either = editor.addNewChildAndPutAttribute(path, 0, key, value);
+            Assert.assertFalse(either.isA());
+            editor = either.b();
+            either = editor.success();
+            Assert.assertFalse(either.isA());
+
+            TreeNode rootNode = tree.getRootNode();
+            JungleNodeIterator iterator = new JungleNodeIterator(rootNode);
+            int nodeCount = 0;
+            List<String> list = new LinkedList<>();
+            for (int i = 1; i <= count; i++) {
+                list.add(("value" + i));
+            }
+
+
+            while (iterator.hasNext()) { //ちゃんとノードの追加ができているか、全てのノードが木にあるかをを調べる
+                nodeCount++;
+                TreeNode n = iterator.next();
+                Attributes attribute = n.getAttributes();
+                String str = attribute.getString(key);
+                int index = list.indexOf(str);
+                list.remove(index);
+            }
+
+            Assert.assertEquals(list.size(), 0);
+            int expectCount = count;
+            Assert.assertEquals(expectCount, nodeCount);
+
+            ColorlessTreeNode rootNode2 = (ColorlessTreeNode) rootNode; //test用methodを使うためにcastしている
+            rootNode2.checkDepth(0, 0); //赤黒木のバランスが取れているかを調べる
+        }
+
+        System.out.println("------------------------------------------- delete -----------------------------------------------------------------------------------");
+        for (int count = 1; count <= testCount; count++) {
+            JungleTreeEditor editor = tree.getJungleTreeEditor();
+            ByteBuffer value = ByteBuffer.wrap(("value" + count).getBytes());
+            Either<Error, JungleTreeEditor> either = editor.deleteChildAt(path, 0, key, value);
+            Assert.assertFalse(either.isA());
+            editor = either.b();
+            either = editor.success();
+            Assert.assertFalse(either.isA());
+
+            ColorlessTreeNode rootNode = (ColorlessTreeNode) tree.getRootNode();
+            Iterator<TreeNode> iterator = new JungleNodeIterator(rootNode);
+            int nodeCount = 0;
+
+            while (iterator.hasNext() && rootNode.getAttributes().get(key) != null) { //削除時間違えて他のノードを消してないかを調べる
+                ColorlessTreeNode node = (ColorlessTreeNode) iterator.next();
+                ByteBuffer seach = node.getAttributes().get(key);
+                Assert.assertTrue(rootNode.get(seach));
+                nodeCount++;
+            }
+
+            int expectCount = testCount - count;
+            Assert.assertEquals(expectCount, nodeCount);
+        }
+
+
+    }
+}
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/jungle/core/treeeditor/RedBlack/RedBlackTreeEditorTest.java	Thu Jan 05 09:49:20 2017 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-package jp.ac.u_ryukyu.ie.cr.jungle.core.treeeditor.RedBlack;
-
-import jp.ac.u_ryukyu.ie.cr.jungle.DefaultJungle;
-import jp.ac.u_ryukyu.ie.cr.jungle.Jungle;
-import jp.ac.u_ryukyu.ie.cr.jungle.core.Attributes;
-import jp.ac.u_ryukyu.ie.cr.jungle.query.JungleNodeIterator;
-import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.DefaultNodePath;
-import jp.ac.u_ryukyu.ie.cr.jungle.store.nodepath.NodePath;
-import jp.ac.u_ryukyu.ie.cr.jungle.transaction.editor.jungleTreeEditor.JungleTreeEditor;
-import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
-import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.redBlackTree.ColorlessTreeNode;
-import jp.ac.u_ryukyu.ie.cr.jungle.traverser.DefaultTraverser;
-import jp.ac.u_ryukyu.ie.cr.jungle.tree.JungleTree;
-import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
-import jp.ac.u_ryukyu.ie.cr.jungle.util.Error.Error;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.nio.ByteBuffer;
-import java.util.LinkedList;
-import java.util.List;
-
-public class RedBlackTreeEditorTest {
-
-    int testCount = 5000;
-
-    @Test
-    public void RedBlackTreeEditor() {
-
-        ByteBuffer b5 =  ByteBuffer.wrap(("value" + 5).getBytes());
-        ByteBuffer b6 =  ByteBuffer.wrap(("value" + 6).getBytes());
-        ByteBuffer b12 =  ByteBuffer.wrap(("value" + 12).getBytes());
-        ByteBuffer b8 =  ByteBuffer.wrap(("value" + 8).getBytes());
-
-        long h5 = b5.hashCode();
-        long h6 = b6.hashCode();
-        long h12 = b12.hashCode();
-        long result1 = h6 - h12;
-        long result2 = h5 - h12;
-
-        String key = "balanceKey";
-        Jungle jungle = new DefaultJungle(null, "hogehoge", new DefaultTraverser());
-        JungleTree tree = jungle.createNewRedBlackTree("TreeName", "balanceKey");
-        NodePath path = new DefaultNodePath();
-
-        for (int count = 1; count <= testCount; count++) {
-            JungleTreeEditor editor = tree.getJungleTreeEditor();
-            ByteBuffer value = ByteBuffer.wrap(("value" + count).getBytes());
-            Either<Error, JungleTreeEditor> either = editor.addNewChildAndPutAttribute(path, 0, key, value);
-            Assert.assertFalse(either.isA());
-            editor = either.b();
-            either = editor.success();
-            Assert.assertFalse(either.isA());
-
-            TreeNode rootNode = tree.getRootNode();
-            JungleNodeIterator iterator = new JungleNodeIterator(rootNode);
-            int nodeCount = 0;
-            List<String> list = new LinkedList<>();
-            for (int i = 1; i <= count; i++) {
-                list.add(("value" + i));
-            }
-
-
-            while (iterator.hasNext()) {
-                nodeCount++;
-                TreeNode n = iterator.next();
-                Attributes attribute = n.getAttributes();
-                String str = attribute.getString(key);
-                int index = list.indexOf(str);
-                list.remove(index);
-            }
-
-            Assert.assertEquals(list.size(), 0);
-            int expectCount = count;
-            Assert.assertEquals(expectCount, nodeCount);
-
-            ColorlessTreeNode rootNode2 = (ColorlessTreeNode) rootNode; //test用methodを使うためにcastしている
-            rootNode2.checkDepth(0, 0);
-        }
-
-        System.out.println("------------------------------------------- delete -----------------------------------------------------------------------------------");
-        for (int count = 1; count <= testCount; count++) {
-            System.out.println(count + "回目------------------------------------------------------------------------------------------------------------------------");
-
-            ColorlessTreeNode rootNode = (ColorlessTreeNode) tree.getRootNode();
-            JungleNodeIterator iterator = new JungleNodeIterator(rootNode);
-            int nodeCount = 0;
-
-            if (count == 2)
-                System.out.println("やばい");
-            System.out.println("------------------------------------------------delete 前------------------------------------------------------------------------");
-            while (iterator.hasNext() && rootNode.getAttributes().get(key) != null) {
-                ColorlessTreeNode node = (ColorlessTreeNode) iterator.next();
-                if (node.empty())
-                    System.out.println(node.empty());
-                if (node.key() == null)
-                    System.out.println("これはやばいですよ");
-                ByteBuffer seach = node.getAttributes().get(key);
-                int test = seach.hashCode();
-                String seachStr = node.getAttributes().getString(key);
-                System.out.println(seachStr);
-                Assert.assertTrue(rootNode.get(seach));
-                nodeCount++;
-            }
-
-
-            if (count == 2)
-                System.out.println("やばい");
-            JungleTreeEditor editor = tree.getJungleTreeEditor();
-            ByteBuffer value = ByteBuffer.wrap(("value" + count).getBytes());
-            Either<Error, JungleTreeEditor> either = editor.deleteChildAt(path, 0, key, value);
-            Assert.assertFalse(either.isA());
-            editor = either.b();
-            either = editor.success();
-            Assert.assertFalse(either.isA());
-
-            System.out.println("------------------------------------------------delete 後------------------------------------------------------------------------");
-            rootNode = (ColorlessTreeNode) tree.getRootNode();
-            iterator = new JungleNodeIterator(rootNode);
-            nodeCount = 0;
-
-            while (iterator.hasNext() && rootNode.getAttributes().get(key) != null) {
-                ColorlessTreeNode node = (ColorlessTreeNode) iterator.next();
-                if (node.empty())
-                    System.out.println(node.empty());
-                if (node.key() == null)
-                    System.out.println("これはやばいですよ");
-                System.out.println(node.getAttributes().getString(key));
-                ByteBuffer seach = node.getAttributes().get(key);
-                int test = seach.hashCode();
-                String seachStr= node.getAttributes().getString(key);
-                Assert.assertTrue(rootNode.get(seach));
-                nodeCount++;
-            }
-
-            int expectCount = testCount - count;
-            Assert.assertEquals(expectCount, nodeCount);
-        }
-
-
-    }
-}