changeset 144:0854f9a9e81d

change attrs form TreeMap<String , ByteBuffer> → TreeMap<String,List<ByteBuffer>>
author one
date Sun, 16 Nov 2014 06:40:48 +0900
parents afbe19c98f53
children a2c374a2686b
files src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/App.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/Attributes.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/TreeNodeAttributes.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/logger/LoggingAttributes.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNode.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNodeAttribute.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNodeChildren.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/traverser/InterfaceTraverser.java src/main/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/store/index/DeleteIndexEditor.java src/test/java/DefaultJungleTreeTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/AttributesTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/GetOldTreeTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/impl/treeeditor/DefaultTreeEditorTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/nodeeditor/DeleteAttributeAtTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/nodeeditor/PutAttributeTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/clonable/DefaultTreeNodeAttributesTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultAttributesTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultChildrenTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultNodeTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/traverse/TraverserTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/functionaljava/FjListTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/AddChildrenIndexTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/AttributeIndexTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/DeleteChildrenIndexTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/IndexCommitTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/query/SearchQueryTest.java
diffstat 26 files changed, 438 insertions(+), 358 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/App.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/App.java	Sun Nov 16 06:40:48 2014 +0900
@@ -2,6 +2,7 @@
 
 import java.nio.ByteBuffer;
 
+import fj.data.List;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.DefaultJungle;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTree;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTreeEditor;
@@ -35,7 +36,8 @@
     	
     	
     	TreeNode root = tree.getRootNode();
-    	ByteBuffer v = root.getAttributes().get(key);
+    	List<ByteBuffer> valueList = root.getAttributes().get(key);
+    	ByteBuffer v = valueList.head();
     	String str = new String(v.array());
     	System.out.println(str);
     }
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/Attributes.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/Attributes.java	Sun Nov 16 06:40:48 2014 +0900
@@ -1,9 +1,12 @@
 package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core;
 
 import java.nio.ByteBuffer;
+import java.util.Iterator;
+
+import fj.data.List;
 
 public interface Attributes
 {
-	public ByteBuffer get(String key);
-	public String getString(String key);
+	public List<ByteBuffer> get(String key);
+	public Iterator<String> getString(String key);
 }
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/TreeNodeAttributes.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/TreeNodeAttributes.java	Sun Nov 16 06:40:48 2014 +0900
@@ -12,6 +12,6 @@
 {
 	public Either<Error,TreeNode> delete(String key);
 	public Either<Error,TreeNode> put(String key,ByteBuffer value);
-	public TreeMap<String,ByteBuffer> getAttributesAsRawMap();
+	public TreeMap<String, List<ByteBuffer>> getAttributesAsRawMap();
 	public List<String> getKeys(); 
 }
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/logger/LoggingAttributes.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/logger/LoggingAttributes.java	Sun Nov 16 06:40:48 2014 +0900
@@ -2,6 +2,7 @@
 
 import java.nio.ByteBuffer;
 
+import fj.data.List;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNode;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNodeAttributes;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.operations.DeleteAttributeOperation;
@@ -22,7 +23,7 @@
 		log = _log;
 	}
 
-	public ByteBuffer get(String _key)
+	public List<ByteBuffer> get(String _key)
 	{
 		TreeNodeAttributes attributes = wrap.getAttributes();
 		return attributes.get(_key);
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNode.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNode.java	Sun Nov 16 06:40:48 2014 +0900
@@ -12,18 +12,18 @@
 {
 	//private final DefaultNode wrap;
 	private List<TreeNode> children;
-	private TreeMap<String,ByteBuffer> attrs;
+	private TreeMap<String,List<ByteBuffer>> attrs;
 	private OperationLog log;
 	
 	private static final List<TreeNode> NIL_LIST = List.nil();
-	private static final TreeMap<String,ByteBuffer> NIL_MAP = TreeMap.empty(Ord.stringOrd);
+	private static final TreeMap<String,List<ByteBuffer>> NIL_MAP = TreeMap.empty(Ord.stringOrd);
 	
 	public DefaultTreeNode()
 	{
 		this(NIL_LIST,NIL_MAP);
 	}
 	
-	public DefaultTreeNode(List<TreeNode> _children,TreeMap<String,ByteBuffer> _attrs)
+	public DefaultTreeNode(List<TreeNode> _children,TreeMap<String,List<ByteBuffer>> _attrs)
 	{
 		attrs = _attrs;
 		children = _children;
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNodeAttribute.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNodeAttribute.java	Sun Nov 16 06:40:48 2014 +0900
@@ -1,10 +1,12 @@
 package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction;
 
 import java.nio.ByteBuffer;
+import java.util.Iterator;
 
 import fj.data.List;
 import fj.data.Option;
 import fj.data.TreeMap;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.NulIterator;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNode;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNodeAttributes;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.DefaultOperationLog;
@@ -16,80 +18,105 @@
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Either;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Error;
 
-public class DefaultTreeNodeAttribute implements TreeNodeAttributes
-{
-	public List<TreeNode> children;
-	public TreeMap<String,ByteBuffer> attrs;
-	OperationLog log ;
-	
-	public DefaultTreeNodeAttribute(List<TreeNode> _children,TreeMap<String,ByteBuffer> _attrs)
-	{
-		children = _children;
-		attrs = _attrs;
-		log = new DefaultOperationLog();
-	}
-	
-	public DefaultTreeNodeAttribute(List<TreeNode> _children,TreeMap<String,ByteBuffer> _attrs,OperationLog _log)
-	{
-		children = _children;
-		attrs = _attrs;
-		log = _log;
-	}
+public class DefaultTreeNodeAttribute implements TreeNodeAttributes {
+  public List<TreeNode> children;
+  public TreeMap<String, List<ByteBuffer>> attrs;
+  OperationLog log;
+
+  public DefaultTreeNodeAttribute(List<TreeNode> _children, TreeMap<String, List<ByteBuffer>> _attrs) {
+    children = _children;
+    attrs = _attrs;
+    log = new DefaultOperationLog();
+  }
 
-	@Override
-	public TreeMap<String,ByteBuffer> getAttributesAsRawMap(){
-		return attrs;
-	}
-	
-	@Override
-	public Either<Error,TreeNode> delete(String _key)
-	{
-		if (_key == null) {
-			return DefaultEither.newA(NodeEditorError.NULL_VALUE_NOT_ALLOWED);
-		}
-		
-		if (!attrs.contains(_key)) {
-			return DefaultEither.newA(NodeEditorError.DELETE_KEY_NOT_FOUND);
-		}
-		
-		TreeMap<String,ByteBuffer> newMap = attrs.delete(_key);
-		TreeNode newNode = new DefaultTreeNode(children,newMap);
-		return DefaultEither.newB(newNode);
-	}
+  public DefaultTreeNodeAttribute(List<TreeNode> _children, TreeMap<String, List<ByteBuffer>> _attrs, OperationLog _log) {
+    children = _children;
+    attrs = _attrs;
+    log = _log;
+  }
 
-	@Override
-	public Either<Error,TreeNode> put(String _key, ByteBuffer _value)
-	{
-		if (_key == null || _value == null) {
-			return DefaultEither.newA(NodeEditorError.NULL_VALUE_NOT_ALLOWED);
-		}
-		
-		TreeMap<String,ByteBuffer> newMap = attrs.set(_key,_value);
-		TreeNode newNode = new DefaultTreeNode(children,newMap);
-		return DefaultEither.newB(newNode);
-	}
+  @Override
+  public TreeMap<String, List<ByteBuffer>> getAttributesAsRawMap() {
+    return attrs;
+  }
 
-	@Override
-	public ByteBuffer get(String _key)
-	{
-		if (_key == null) {
-			return null;
-		}
-		
-		Option<ByteBuffer> result = attrs.get(_key);
-		return result.isSome() ? result.some() : null;
-	}
+  @Override
+  public Either<Error, TreeNode> delete(String _key) {
+    if (_key == null) {
+      return DefaultEither.newA(NodeEditorError.NULL_VALUE_NOT_ALLOWED);
+    }
 
-    @Override
-    public String getString(String key) {
-        ByteBuffer attribute = get(key);
-        if (attribute != null)
-            return new String(attribute.array());
-        return null;
+    if (!attrs.contains(_key)) {
+      return DefaultEither.newA(NodeEditorError.DELETE_KEY_NOT_FOUND);
     }
 
-    @Override
-    public List<String> getKeys() {
-      return attrs.keys();
+    TreeMap<String, List<ByteBuffer>> newMap = attrs.delete(_key);
+    TreeNode newNode = new DefaultTreeNode(children, newMap);
+    return DefaultEither.newB(newNode);
+  }
+
+  @Override
+  public Either<Error, TreeNode> put(String _key, ByteBuffer _value) {
+    if (_key == null || _value == null) {
+      return DefaultEither.newA(NodeEditorError.NULL_VALUE_NOT_ALLOWED);
+    }
+    Option<List<ByteBuffer>> attrsListOp = attrs.get(_key);
+
+    List<ByteBuffer> newAttrsList;
+    if (attrsListOp.isNone()) {
+      List<ByteBuffer> attrsList = List.nil();
+      newAttrsList = attrsList.cons(_value);
+    } else {
+      List<ByteBuffer> attrsList = attrsListOp.some();
+      newAttrsList = attrsList.cons(_value);
+    }
+
+    TreeMap<String, List<ByteBuffer>> newMap = attrs.set(_key, newAttrsList);
+    TreeNode newNode = new DefaultTreeNode(children, newMap);
+    return DefaultEither.newB(newNode);
+  }
+
+  @Override
+  public List<ByteBuffer> get(String _key) {
+    if (_key == null) {
+      return List.nil();
     }
+
+    Option<List<ByteBuffer>> result = attrs.get(_key);
+    return result.isSome() ? result.some() : List.nil();
+  }
+
+  @Override
+  public Iterator<String> getString(String key) {
+    List<ByteBuffer> attributeList = get(key);
+    if (attributeList == null)
+      return new NulIterator<>();
+
+    return new Iterator<String>() {
+
+      List<ByteBuffer> iteratorAttributeList = attributeList;
+      ByteBuffer attribute;
+
+      @Override
+      public boolean hasNext() {
+        if (!iteratorAttributeList.isEmpty()) {
+          attribute = iteratorAttributeList.head();
+          iteratorAttributeList = iteratorAttributeList.tail();
+          return true;
+        }
+        return false;
+      }
+
+      @Override
+      public String next() {
+        return new String(attribute.array());
+      }
+
+    };
+  }
+
+  @Override
+  public List<String> getKeys() {
+    return attrs.keys();
+  }
 }
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNodeChildren.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNodeChildren.java	Sun Nov 16 06:40:48 2014 +0900
@@ -8,11 +8,6 @@
 import fj.data.TreeMap;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNode;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNodeChildren;
-import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.DefaultOperationLog;
-import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.OperationLog;
-import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.operations.AppendChildAtOperation;
-import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.operations.DeleteChildAtOperation;
-import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.operations.NodeOperation;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.NodeEditorError;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.DefaultEither;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.util.Either;
@@ -30,9 +25,9 @@
 	}
 	
 	public List<TreeNode> children;
-	public TreeMap<String,ByteBuffer> attrs;
+	public TreeMap<String,List<ByteBuffer>> attrs;
 
-	public DefaultTreeNodeChildren(List<TreeNode> _children,TreeMap<String,ByteBuffer> _attrs)
+	public DefaultTreeNodeChildren(List<TreeNode> _children,TreeMap<String,List<ByteBuffer>> _attrs)
 	{
 		children = _children;
 		attrs = _attrs;
@@ -112,7 +107,7 @@
 	@Override
 	public Either<Error,TreeNode> at(int _pos)
 	{
-    if(!boundaryCheck(_pos)){
+    if(!boundaryCheck(_pos + 1)){
       return DefaultEither.newA(NodeEditorError.INDEX_OUT_OF_BOUNDS);
     }
 
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/traverser/InterfaceTraverser.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/traverser/InterfaceTraverser.java	Sun Nov 16 06:40:48 2014 +0900
@@ -292,10 +292,11 @@
 
           for (; itNode.hasNext();) {
             Pair<TreeNode, NodePath> pathNode = itNode.next();
-            String value = pathNode.left().getAttributes().getString(key);
+            Iterator<String> valueIterator = pathNode.left().getAttributes().getString(key);
             Option<TreeMap<String, List<NodePath>>> innerIndexOp = index.get(key);
 
-            if (value != null) {
+            for (;valueIterator.hasNext();) {
+              String value = valueIterator.next();
               if (innerIndexOp.isNone()) {
 
                 TreeMap<String, List<NodePath>> innerIndex = TreeMap.empty(Ord.stringOrd);
@@ -405,10 +406,11 @@
 
           for (; itNode.hasNext();) {
             Pair<TreeNode, NodePath> pathNode = itNode.next();
-            String value = pathNode.left().getAttributes().getString(key);
+            Iterator<String> valueIterator = pathNode.left().getAttributes().getString(key);
             Option<TreeMap<String, List<NodePath>>> innerIndexOp = index.get(key);
 
-            if (value != null) {
+            for (;valueIterator.hasNext();) {
+              String value = valueIterator.next();
               if (innerIndexOp.isNone()) {
 
                 TreeMap<String, List<NodePath>> innerIndex = TreeMap.empty(Ord.stringOrd);
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/store/index/DeleteIndexEditor.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/store/index/DeleteIndexEditor.java	Sun Nov 16 06:40:48 2014 +0900
@@ -1,6 +1,7 @@
 package jp.ac.u_ryukyu.ie.cr.tatsuki.jungle.store.index;
 
 import java.nio.ByteBuffer;
+import java.util.Iterator;
 
 import fj.data.List;
 import fj.data.Option;
@@ -35,8 +36,12 @@
 	public Either<Error, IndexJungleTreeEditor> edit(TreeNode root,TransactionManager txManager,TreeEditor editor,TreeOperationLog log,TreeMap<String, TreeMap<String, List<NodePath>>> index) {
 		NodePath newPath = path.pop().right();
 		TreeNode target = getTarget(node, newPath);
-		String attribute = target.getAttributes().getString(key);
-		TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = editIndex(attribute, index);
+		TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = index;
+		Iterator<String> attributeIterator = target.getAttributes().getString(key);
+		for (;attributeIterator.hasNext();){
+		  String attribute = attributeIterator.next();
+		  newIndex = editIndex(attribute, newIndex);
+		}
 		IndexJungleTreeEditor newEditor = new IndexJungleTreeEditor(root,txManager,editor,log, newIndex);
 		Either<Error, IndexJungleTreeEditor> either = DefaultEither.newB(newEditor);
 		return either;
--- a/src/test/java/DefaultJungleTreeTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/DefaultJungleTreeTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -1,5 +1,6 @@
 import java.nio.ByteBuffer;
 
+import fj.data.List;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.DefaultJungle;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.Jungle;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTree;
@@ -45,7 +46,8 @@
 		
 		// check the value ;
 		TreeNode node = tree.getRootNode();
-		ByteBuffer v = node.getAttributes().get(key);
+		List<ByteBuffer> valueList = node.getAttributes().get(key);
+		ByteBuffer v = valueList.head();
 		Assert.assertEquals(0,v.compareTo(value));
 	   Assert.assertEquals(1,tree.revision());
 		// editor2 must fail transction
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/AttributesTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/AttributesTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -12,10 +12,10 @@
 public abstract class AttributesTest extends TestCase
 {
 	@SuppressWarnings("unchecked")
-	public static List<P2<String,ByteBuffer>> ENTRIES = List.list(
-		P.p("KEY1",ByteBuffer.wrap("VALUE1".getBytes())),
-		P.p("KEY2",ByteBuffer.wrap("VALUE2".getBytes())),
-		P.p("KEY3",ByteBuffer.wrap("VALUE3".getBytes()))
+	public static List<P2<String,List<ByteBuffer>>> ENTRIES = List.list(
+		P.p("KEY1",List.list(ByteBuffer.wrap("VALUE1".getBytes()))),
+		P.p("KEY2",List.list(ByteBuffer.wrap("VALUE2".getBytes()))),
+		P.p("KEY3",List.list(ByteBuffer.wrap("VALUE3".getBytes())))
 	);
 	
 	public abstract Attributes instance();
@@ -24,10 +24,12 @@
 	{
 		Attributes attrs = instance();
 		
-		for(P2<String,ByteBuffer> entry : ENTRIES){
+		for(P2<String,List<ByteBuffer>> entry : ENTRIES){
 			String key = entry._1();
-			ByteBuffer expect = entry._2();
-			ByteBuffer actual = attrs.get(key);
+			List<ByteBuffer> expectList = entry._2();
+			List<ByteBuffer> actualList = attrs.get(key);
+			ByteBuffer expect = expectList.head();
+			ByteBuffer actual = actualList.head();
 			Assert.assertNotNull(actual);
 			Assert.assertEquals(0,actual.compareTo(expect));
 		}
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/GetOldTreeTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/GetOldTreeTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -1,6 +1,7 @@
 package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core;
 
 import java.nio.ByteBuffer;
+import java.util.Iterator;
 
 import org.junit.Test;
 
@@ -28,8 +29,7 @@
 
     for (int num = 0; num < 10; num++) {
       JungleTreeEditor addChildEditor = editor.addNewChildAt(path, num).b();
-      JungleTreeEditor putAttributeEditor = addChildEditor.putAttribute(path.add(num), "test",
-          ByteBuffer.wrap("tatsuki".getBytes())).b();
+      JungleTreeEditor putAttributeEditor = addChildEditor.putAttribute(path.add(num), "test", ByteBuffer.wrap("tatsuki".getBytes())).b();
       Either<Error, JungleTreeEditor> successEither = putAttributeEditor.success();
       Assert.assertFalse(successEither.isA());
       editor = successEither.b();
@@ -43,16 +43,22 @@
     Either<Error, TreeNode> childNodeEither = root.getChildren().at(9);
     Assert.assertTrue(childNodeEither.isB());
     TreeNode child = childNodeEither.b();
-    Assert.assertEquals(child.getAttributes().getString("test"),"kanagawa");
-    long t1 = System.currentTimeMillis();
+    Iterator<String> valueIterator = child.getAttributes().getString("test");
+    Assert.assertTrue(valueIterator.hasNext());
+    String value = valueIterator.next();
+    Assert.assertEquals(value,"kanagawa");
+    
     JungleTree oldTree1 = tree.getOldTree(10).b();
-    long t2 = System.currentTimeMillis();
-    System.out.println("time = " + (t2 - t1));
+    
     TreeNode oldRoot1 = oldTree1.getRootNode();
     Either<Error, TreeNode> oldChildNodeEither = oldRoot1.getChildren().at(9);
     Assert.assertTrue(oldChildNodeEither.isB());
+    
     TreeNode oldChildNode = oldChildNodeEither.b();
-    Assert.assertEquals(oldChildNode.getAttributes().getString("test"),"tatsuki");
+    Iterator<String> oldValueIterator = oldChildNode.getAttributes().getString("test");
+    Assert.assertTrue(oldValueIterator.hasNext());
+    String oldValue = oldValueIterator.next();
+    Assert.assertEquals(oldValue,"tatsuki");
     
     
     JungleTree oldTree2 = tree.getOldTree(9).b();
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/impl/treeeditor/DefaultTreeEditorTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/impl/treeeditor/DefaultTreeEditorTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -1,7 +1,9 @@
 package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.impl.treeeditor;
 
 import java.nio.ByteBuffer;
+import java.util.Iterator;
 
+import fj.data.List;
 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.TreeNode;
@@ -53,15 +55,16 @@
 		DefaultTraverser traverser = new DefaultTraverser();
 		
 		for(DefaultNodePath part : path.inits()){
+		  System.out.println(part.toString());
 			Either<Error,Traversal> either = traverser.traverse(newRoot,new DefaultEvaluator(part));
 			if(either.isA()){
 				Assert.fail();
 			}
 			TreeNode target = either.b().destination();
 			String expected = part.toString();
-			String actual = new String(target.getAttributes().get(key).array());
-			
-			Assert.assertEquals(expected,actual);
+			Iterator<String> actualIterator = target.getAttributes().getString(key);
+			Assert.assertTrue(actualIterator.hasNext());
+			Assert.assertEquals(expected,actualIterator.next());
 		}
 		
 		for(DefaultNodePath part : path.inits()){
@@ -70,9 +73,9 @@
 				Assert.fail();
 			}
 			TreeNode target = either.b().destination();
-			ByteBuffer actual = target.getAttributes().get(key);
-			
-			Assert.assertNull(actual);
+			System.out.println(part.toString());
+			List<ByteBuffer> actualList = target.getAttributes().get(key);
+			Assert.assertTrue(actualList.isEmpty());
 		}
 		
 	}
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/nodeeditor/DeleteAttributeAtTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/nodeeditor/DeleteAttributeAtTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -2,6 +2,7 @@
 
 import java.nio.ByteBuffer;
 
+import fj.data.List;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNode;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.LoggingNode;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.DeleteAttribute;
@@ -31,7 +32,7 @@
 			Assert.fail();
 		}
 		LoggingNode newNode = either2.b();
-		ByteBuffer ret = newNode.getAttributes().get(key);
-		Assert.assertNull(ret);
+		List<ByteBuffer> retList = newNode.getAttributes().get(key);
+		Assert.assertTrue(retList.isEmpty());
 	}
 }
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/nodeeditor/PutAttributeTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/nodeeditor/PutAttributeTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -4,6 +4,7 @@
 
 import org.junit.Assert;
 
+import fj.data.List;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNode;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.LoggingNode;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.trasnformer.PutAttribute;
@@ -27,7 +28,8 @@
 		}
 		
 		LoggingNode newNode = either.b();
-		ByteBuffer ret = newNode.getAttributes().get(key);
+		List<ByteBuffer> retList = newNode.getAttributes().get(key);
+		ByteBuffer ret = retList.head();
 		Assert.assertEquals(0,ret.compareTo(value));
 	}
 }
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/clonable/DefaultTreeNodeAttributesTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/clonable/DefaultTreeNodeAttributesTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -10,7 +10,6 @@
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.core.AttributesTest;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNode;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.DefaultTreeNode;
-import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.DefaultTreeNodeAttribute;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
@@ -27,9 +26,9 @@
 	public static DefaultTreeNode instance()
 	{
 		List<TreeNode> rawList = List.nil();
-		TreeMap<String,ByteBuffer> rawMap = TreeMap.empty(Ord.stringOrd);
+		TreeMap<String,List<ByteBuffer>> rawMap = TreeMap.empty(Ord.stringOrd);
 		
-		for(P2<String,ByteBuffer> entry : AttributesTest.ENTRIES){
+		for(P2<String,List<ByteBuffer>> entry : AttributesTest.ENTRIES){
 			rawMap = rawMap.set(entry._1(),entry._2());
 		}
 		
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultAttributesTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultAttributesTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -19,11 +19,11 @@
 	public TreeNodeAttributes instance()
 	{
 		List<TreeNode> rawList = List.nil();
-		TreeMap<String,ByteBuffer> rawMap = TreeMap.empty(Ord.stringOrd);
+		TreeMap<String,List<ByteBuffer>> rawMap = TreeMap.empty(Ord.stringOrd);
 		
 		// add attributes
 		
-		for(P2<String, ByteBuffer> entry : ENTRIES){
+		for(P2<String, List<ByteBuffer>> entry : ENTRIES){
 			rawMap = rawMap.set(entry._1(),entry._2());
 		}
 		
@@ -34,22 +34,22 @@
 	public void testGetAttributesAsRawMap()
 	{
 		TreeNodeAttributes attrs = instance();
-		TreeMap<String,ByteBuffer> rawMap = attrs.getAttributesAsRawMap();
+		TreeMap<String,List<ByteBuffer>> rawMap = attrs.getAttributesAsRawMap();
 		
 		// testing rawmap is not null.
 		Assert.assertNotNull(rawMap);
 		
 		// testing rawmap has correct key values.
-		for(P2<String,ByteBuffer> entry : ENTRIES){
+		for(P2<String,List<ByteBuffer>> entry : ENTRIES){
 			String key = entry._1();
-			ByteBuffer value = entry._2();
+			ByteBuffer value = entry._2().head();
 			
-			Option<ByteBuffer> option = rawMap.get(key);
+			Option<List<ByteBuffer>> option = rawMap.get(key);
 			if(option.isNone()){
 				Assert.fail();
 			}
 			
-			ByteBuffer actual = option.some();
+			ByteBuffer actual = option.some().head();
 			Assert.assertEquals(0,actual.compareTo(value));
 		}
 	}
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultChildrenTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultChildrenTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -23,7 +23,7 @@
 			rawList = rawList.cons(new DefaultTreeNode());
 		}
 		
-		TreeMap<String,ByteBuffer> rawMap = TreeMap.empty(Ord.stringOrd);
+		TreeMap<String,List<ByteBuffer>> rawMap = TreeMap.empty(Ord.stringOrd);
 		
 		return new DefaultTreeNode(rawList,rawMap).getChildren();
 	}
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultNodeTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultNodeTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -30,7 +30,7 @@
 	public static DefaultTreeNode instance()
 	{
 		List<TreeNode> rawList = List.nil();
-		TreeMap<String,ByteBuffer> rawMap = TreeMap.empty(Ord.stringOrd);
+		TreeMap<String,List<ByteBuffer>> rawMap = TreeMap.empty(Ord.stringOrd);
 		DefaultTreeNode node = new DefaultTreeNode(rawList,rawMap);
 		
 		return node;
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/traverse/TraverserTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/traverse/TraverserTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -43,7 +43,8 @@
 			Traversal traversal = ret.b();
 			TreeNode target = traversal.destination();
 			String expect = path.toString();
-			ByteBuffer value = target.getAttributes().get(key);
+			List<ByteBuffer> valueList = target.getAttributes().get(key);
+			ByteBuffer value = valueList.head();
 			String actual = new String(value.array());
 			Assert.assertEquals(expect,actual);
 			
@@ -52,7 +53,7 @@
 			for(Direction<TreeNode> d : traversal){
 				DefaultNodePath part = parts.head();
 				parts = parts.tail();
-				value = d.getTarget().getAttributes().get(key);
+				value = d.getTarget().getAttributes().get(key).head();
 				String actualCurrentPathStr = new String(value.array());
 				String expectCurrentPathStr = part.toString();
 				Assert.assertEquals(expectCurrentPathStr,actualCurrentPathStr);
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/functionaljava/FjListTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/functionaljava/FjListTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -1,11 +1,14 @@
 package jp.ac.u_ryukyu.ie.cr.tatsuki.functionaljava;
 
+import java.nio.ByteBuffer;
+
 import fj.F;
 import fj.data.List;
 
 public class FjListTest {
 
   static public void main(String args[]){
+    
     List<String> list = List.nil();
     list = list.cons("wei");
     String aaa = list.head();
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/AddChildrenIndexTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/AddChildrenIndexTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -4,10 +4,8 @@
 import java.util.Iterator;
 
 import org.junit.Test;
-import org.junit.experimental.theories.suppliers.TestedOn;
 
 import fj.data.List;
-import fj.data.Option;
 import fj.data.TreeMap;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.DefaultJungle;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.Jungle;
@@ -28,81 +26,89 @@
 
 public class AddChildrenIndexTest {
 
-	@Test
-	public void AddChildrenTest(){
-		Jungle jungle = new DefaultJungle(null, "hogehoge",new DefaultTreeEditor(new DefaultTraverser()));
-		jungle.createNewTree("tree");
-		JungleTree tree = jungle.getTreeByName("tree");
-		createTree(tree);
-		tree.getRootNode();
-		InterfaceTraverser ifTraverser = tree.getTraverser();
+  @Test
+  public void AddChildrenTest() {
+    Jungle jungle = new DefaultJungle(null, "hogehoge", new DefaultTreeEditor(new DefaultTraverser()));
+    jungle.createNewTree("tree");
+    JungleTree tree = jungle.getTreeByName("tree");
+    createTree(tree);
+    tree.getRootNode();
+    InterfaceTraverser ifTraverser = tree.getTraverser();
 
-		Iterator<Pair<TreeNode, NodePath>> pairIterator = ifTraverser.find((TreeNode node) -> {
-			ByteBuffer attribute = node.getAttributes().get(key);
-			if (attribute != null) {
-				byte[] byteAttribute = attribute.array();
-				String str = new String(byteAttribute);
-				System.out.println("attribute = " + str);
-				return str.equals("<-1,0,1>");
-			}
-			return false;
-		}, key, "<-1,0,1>");
+    Iterator<Pair<TreeNode, NodePath>> pairIterator = ifTraverser.find((TreeNode node) -> {
+      List<ByteBuffer> attributeList = node.getAttributes().get(key);
+      if (attributeList.isNotEmpty()) {
+        for (ByteBuffer attribute : attributeList) {
+          byte[] byteAttribute = attribute.array();
+          String str = new String(byteAttribute);
+          System.out.println("attribute = " + str);
+          if (str.equals("<-1,0,1>"))
+            return true;
+          continue;
+        }
+      }
+      return false;
+    }, key, "<-1,0,1>");
+
+    for (; pairIterator.hasNext(); pairIterator.next()) {
+
+    }
+    ifTraverser.commitIndex();
+
+    IndexJungleTreeEditor editor = tree.getIndexTreeEditor();
+    Either<Error, JungleTreeEditor> either = editor.addNewChildAt(new DefaultNodePath().add(0), 0);
+    either.b().success();
+
+    InterfaceTraverser newIfTraverser = tree.getTraverser();
+    TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = newIfTraverser.getIndex();
+    NodePath targetPath = newIndex.get(key).some().get("<-1,0,2>").some().head();
+    TreeNode targetNode = getTarget(tree.getRootNode(), targetPath);
+    Iterator<String> attributeIterator = targetNode.getAttributes().getString(key);
+    Assert.assertTrue(attributeIterator.hasNext());
+    String attribute = attributeIterator.next();
+    Assert.assertEquals(attribute, "<-1,0,1>");
 
-		 for (;pairIterator.hasNext();pairIterator.next()) {
-			 
-		 }
-		ifTraverser.commitIndex(); 
-		
-		IndexJungleTreeEditor editor = tree.getIndexTreeEditor();
-		Either<Error, JungleTreeEditor> either = editor.addNewChildAt(new DefaultNodePath().add(0), 0);
-		either.b().success();
-		
-		InterfaceTraverser newIfTraverser = tree.getTraverser();
-		TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = newIfTraverser.getIndex();
-		NodePath targetPath = newIndex.get(key).some().get("<-1,0,2>").some().head();
-		TreeNode targetNode = getTarget(tree.getRootNode(), targetPath);
-		Assert.assertEquals(targetNode.getAttributes().getString(key) ,"<-1,0,1>");
-		
-		}
-	public static String key = "KEY";
-	public static DefaultTreeNode factory = new DefaultTreeNode();
+  }
+
+  public static String key = "KEY";
+  public static DefaultTreeNode factory = new DefaultTreeNode();
+
+  public void createTree(JungleTree tree) {
+    NodePath root = new DefaultNodePath();
+    createChildren(tree, root, 0);
 
-	public void createTree(JungleTree tree) {
-		NodePath root = new DefaultNodePath();
-		createChildren(tree, root, 0);
+    for (int x = 0; x < 3; x++) {
+      createChildren(tree, root.add(0), x);
+      for (int y = 0; y < 3; y++) {
+        createChildren(tree, root.add(0).add(x), y);
+      }
+    }
+
+  }
 
-		for (int x = 0; x < 3; x++) {
-			createChildren(tree, root.add(0), x);
-			for (int y = 0; y < 3; y++) {
-				createChildren(tree, root.add(0).add(x), y);
-			}
-		}
-
-	}
+  public void createChildren(JungleTree tree, NodePath root, int num) {
+    JungleTreeEditor editor = tree.getTreeEditor();// Treeのeditorを作成
+    Either<Error, JungleTreeEditor> either = editor.addNewChildAt(root, num); // 新しく入れるところへのパス
+    if (either.isA()) {
+      Assert.fail();
+    }
+    editor = either.b();
+    either = editor.success();
+    if (either.isA()) {
+      Assert.fail();
+    }
+    NodePath childPath = root.add(num);
+    editor = tree.getTreeEditor();
+    NodePath attribute = root.add(num);
+    System.out.println(attribute.toString());
+    either = editor.putAttribute(childPath, key, ByteBuffer.wrap(attribute.toString().getBytes()));
+    if (either.isA()) {
+      Assert.fail();
+    }
+    editor = either.b();
+    either = editor.success();
+  }
 
-	public void createChildren(JungleTree tree, NodePath root, int num) {
-		JungleTreeEditor editor = tree.getTreeEditor();// Treeのeditorを作成
-		Either<Error, JungleTreeEditor> either = editor
-				.addNewChildAt(root, num); // 新しく入れるところへのパス
-		if (either.isA()) {
-			Assert.fail();
-		}
-		editor = either.b();
-		either = editor.success();
-		if (either.isA()) {
-			Assert.fail();
-		}
-		NodePath childPath = root.add(num);
-		editor = tree.getTreeEditor();
-		NodePath attribute = root.add(num);
-		System.out.println(attribute.toString());
-		either = editor.putAttribute(childPath, key,ByteBuffer.wrap(attribute.toString().getBytes()));
-		if (either.isA()) {
-			Assert.fail();
-		}
-		editor = either.b();
-		either = editor.success();
-	}
   public TreeNode getTarget(TreeNode node, NodePath path) {
     Pair<Integer, NodePath> removeHeadPath = path.pop();
 
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/AttributeIndexTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/AttributeIndexTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -1,9 +1,11 @@
 package jp.ac.u_ryukyu.ie.cr.tatsuki.jungle.index;
 
 import java.nio.ByteBuffer;
+import java.util.Iterator;
 
 import org.junit.Test;
 
+
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.DefaultJungle;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTree;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTreeEditor;
@@ -44,7 +46,9 @@
 		
 		NodePath targetPath = index.get("key").some().get("test").some().head();
 		TreeNode targetNode = getTarget(tree.getRootNode(), targetPath);
-		Assert.assertEquals(targetNode.getAttributes().getString("key"),"test");
+		Iterator<String> AttributeIterator = targetNode.getAttributes().getString("key");
+		Assert.assertTrue(AttributeIterator.hasNext());
+		Assert.assertEquals(AttributeIterator.next(),"test");
 		
 		JungleTreeEditor editor4 = tree.getIndexTreeEditor();
 		Either<Error, JungleTreeEditor> either3 = editor4.deleteAttribute(path.add(0), "key");
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/DeleteChildrenIndexTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/DeleteChildrenIndexTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -36,12 +36,16 @@
     InterfaceTraverser ifTraverser = tree.getTraverser();
 
     Iterator<Pair<TreeNode, NodePath>> pairIterator = ifTraverser.find((TreeNode node) -> {
-      ByteBuffer attribute = node.getAttributes().get(key);
-      if (attribute != null) {
-        byte[] byteAttribute = attribute.array();
-        String str = new String(byteAttribute);
-        System.out.println("attribute = " + str);
-        return str.equals("<-1,0,1>");
+      List<ByteBuffer> attributeList = node.getAttributes().get(key);
+      if (attributeList.isNotEmpty()) {
+        for (ByteBuffer attribute : attributeList) {
+          byte[] byteAttribute = attribute.array();
+          String str = new String(byteAttribute);
+          System.out.println("attribute = " + str);
+          if (str.equals("<-1,0,1>"))
+            return true;          
+          continue;
+        }
       }
       return false;
     }, key, "<-1,0,1>");
@@ -62,7 +66,10 @@
     TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = newIfTraverser.getIndex();
     NodePath targetPath = newIndex.get(key).some().get("<-1,0,1>").some().head();
     TreeNode targetNode = getTarget(tree.getRootNode(), targetPath);
-    Assert.assertEquals(targetNode.getAttributes().getString(key), "<-1,0,2>");
+    Iterator<String> attributeIterator = targetNode.getAttributes().getString(key);
+    Assert.assertTrue(attributeIterator.hasNext());
+    String attribute = attributeIterator.next();
+    Assert.assertEquals(attribute, "<-1,0,2>");
 
   }
 
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/IndexCommitTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/index/IndexCommitTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -1,7 +1,5 @@
 package jp.ac.u_ryukyu.ie.cr.tatsuki.jungle.index;
 
-
-
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.DefaultJungle;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.Jungle;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTree;
@@ -19,7 +17,6 @@
 
 import java.nio.ByteBuffer;
 
-
 import org.junit.Test;
 
 import fj.data.List;
@@ -28,113 +25,119 @@
 
 public class IndexCommitTest {
 
-	@Test
-	public void IndexCommitTest() throws InterruptedException {
-		
-		Jungle jungle = new DefaultJungle(null, "hogehoge",new DefaultTreeEditor(new DefaultTraverser()));
-		jungle.createNewTree("tree");
-		JungleTree tree = jungle.getTreeByName("tree");
-		createTree(tree);
-		tree.getRootNode();
-		InterfaceTraverser ifTraverser = tree.getTraverser();
+  @Test
+  public void IndexCommitTest() throws InterruptedException {
 
-		 ifTraverser.find((TreeNode node) -> {
-			ByteBuffer attribute = node.getAttributes().get(key);
-			if (attribute != null) {
-				byte[] byteAttribute = attribute.array();
-				String str = new String(byteAttribute);
-				System.out.println("attribute = " + str);
-				return str.equals("<-1,0,1>");
-			}
-			return false;
-		}, key, "<-1,0,1>");
+    Jungle jungle = new DefaultJungle(null, "hogehoge", new DefaultTreeEditor(new DefaultTraverser()));
+    jungle.createNewTree("tree");
+    JungleTree tree = jungle.getTreeByName("tree");
+    createTree(tree);
+    tree.getRootNode();
+    InterfaceTraverser ifTraverser = tree.getTraverser();
 
-		//check index
-		TreeMap<String, TreeMap<String, List<NodePath>>> index = ifTraverser.getIndex();
-		Option<TreeMap<String, List<NodePath>>> opIndex = index.get(key);
-		
-		Assert.assertTrue(!opIndex.isNone());
-		
-		TreeMap<String, List< NodePath>> innerIndex = opIndex.some();
-		Assert.assertTrue(!innerIndex.get("<-1,0,0>").isNone());
+    ifTraverser.find((TreeNode node) -> {
+      List<ByteBuffer> attributeList = node.getAttributes().get(key);
+      if (attributeList.isNotEmpty()) {
+        for (ByteBuffer attribute : attributeList) {
+          byte[] byteAttribute = attribute.array();
+          String str = new String(byteAttribute);
+          System.out.println("attribute = " + str);
+          if (str.equals("<-1,0,1>"))
+            return true;
+          continue;
+        }
+      }
+      return false;
+    }, key, "<-1,0,1>");
 
-		JungleTreeEditor editor = tree.getTreeEditor();
-		Either<Error, JungleTreeEditor> either = editor.addNewChildAt(new DefaultNodePath(), 0);
-		editor = either.b();
-		editor.success();
-		
-		ifTraverser.commitIndex();
-		JungleTree newTree = jungle.getTreeByName("tree");
-		InterfaceTraverser newIfTraverser = newTree.getTraverser();
-		TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = newIfTraverser.getIndex();
-		Assert.assertTrue(newIndex.isEmpty());
-		
-		InterfaceTraverser ifTraverser1= tree.getTraverser();
+    // check index
+    TreeMap<String, TreeMap<String, List<NodePath>>> index = ifTraverser.getIndex();
+    Option<TreeMap<String, List<NodePath>>> opIndex = index.get(key);
+
+    Assert.assertTrue(!opIndex.isNone());
+
+    TreeMap<String, List<NodePath>> innerIndex = opIndex.some();
+    Assert.assertTrue(!innerIndex.get("<-1,0,0>").isNone());
+
+    JungleTreeEditor editor = tree.getTreeEditor();
+    Either<Error, JungleTreeEditor> either = editor.addNewChildAt(new DefaultNodePath(), 0);
+    editor = either.b();
+    editor.success();
+
+    ifTraverser.commitIndex();
+    JungleTree newTree = jungle.getTreeByName("tree");
+    InterfaceTraverser newIfTraverser = newTree.getTraverser();
+    TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = newIfTraverser.getIndex();
+    Assert.assertTrue(newIndex.isEmpty());
+
+    InterfaceTraverser ifTraverser1 = tree.getTraverser();
 
-		 ifTraverser1.find((TreeNode node) -> {
-			ByteBuffer attribute = node.getAttributes().get(key);
-			if (attribute != null) {
-				byte[] byteAttribute = attribute.array();
-				String str = new String(byteAttribute);
-				System.out.println("attribute = " + str);
-				return str.equals("<-1,0,1>");
-			}
-			return false;
-		}, key, "<-1,0,1>");
-		 
-		ifTraverser1.commitIndex();
-		JungleTree newTree2 = jungle.getTreeByName("tree");
-		InterfaceTraverser newIfTraverser2 = newTree2.getTraverser();
-		TreeMap<String, TreeMap<String, List<NodePath>>> newIndex1 = newIfTraverser2.getIndex();
-		Assert.assertFalse(newIndex1.isEmpty());
+    ifTraverser1.find((TreeNode node) -> {
+      List<ByteBuffer> attributeList = node.getAttributes().get(key);
+      if (attributeList.isNotEmpty()) {
+        for (ByteBuffer attribute : attributeList) {
+          byte[] byteAttribute = attribute.array();
+          String str = new String(byteAttribute);
+          System.out.println("attribute = " + str);
+          if (str.equals("<-1,0,1>"))
+            return true;
+          continue;
+        }
+      }
+      return false;
+    }, key, "<-1,0,1>");
 
-	}
+    ifTraverser1.commitIndex();
+    JungleTree newTree2 = jungle.getTreeByName("tree");
+    InterfaceTraverser newIfTraverser2 = newTree2.getTraverser();
+    TreeMap<String, TreeMap<String, List<NodePath>>> newIndex1 = newIfTraverser2.getIndex();
+    Assert.assertFalse(newIndex1.isEmpty());
+
+  }
 
-	public boolean compare(TreeNode compareNode, String compareAttribute) {
-		String labName = compareNode.getAttributes().getString(key);
-		if (labName.equals(compareAttribute))
-			return true;
-		return false;
-	}
+  public boolean compare(TreeNode compareNode, String compareAttribute) {
+    String labName = compareNode.getAttributes().getString(key).next();
+    if (labName.equals(compareAttribute))
+      return true;
+    return false;
+  }
 
-	public static String key = "KEY";
-	public static DefaultTreeNode factory = new DefaultTreeNode();
-
-	public void createTree(JungleTree tree) {
-		NodePath root = new DefaultNodePath();
-		createChildren(tree, root, 0);
+  public static String key = "KEY";
+  public static DefaultTreeNode factory = new DefaultTreeNode();
 
-		for (int x = 0; x < 2; x++) {
-			createChildren(tree, root.add(0), x);
-			for (int y = 0; y < 2; y++) {
-				createChildren(tree, root.add(0).add(x), y);
-			}
-		}
+  public void createTree(JungleTree tree) {
+    NodePath root = new DefaultNodePath();
+    createChildren(tree, root, 0);
 
-	}
+    for (int x = 0; x < 2; x++) {
+      createChildren(tree, root.add(0), x);
+      for (int y = 0; y < 2; y++) {
+        createChildren(tree, root.add(0).add(x), y);
+      }
+    }
+
+  }
 
-	public void createChildren(JungleTree tree, NodePath root, int num) {
-		JungleTreeEditor editor = tree.getTreeEditor();// Treeのeditorを作成
-		Either<Error, JungleTreeEditor> either = editor
-				.addNewChildAt(root, num); // 新しく入れるところへのパス
-		if (either.isA()) {
-			Assert.fail();
-		}
-		editor = either.b();
-		either = editor.success();
-		if (either.isA()) {
-			Assert.fail();
-		}
-		NodePath childPath = root.add(num);
-		editor = tree.getTreeEditor();
-		NodePath attribute = root.add(num);
-		System.out.println(attribute.toString());
-		either = editor.putAttribute(childPath, key,
-				ByteBuffer.wrap(attribute.toString().getBytes()));
-		if (either.isA()) {
-			Assert.fail();
-		}
-		editor = either.b();
-		either = editor.success();
-	}
+  public void createChildren(JungleTree tree, NodePath root, int num) {
+    JungleTreeEditor editor = tree.getTreeEditor();// Treeのeditorを作成
+    Either<Error, JungleTreeEditor> either = editor.addNewChildAt(root, num); // 新しく入れるところへのパス
+    if (either.isA()) {
+      Assert.fail();
+    }
+    editor = either.b();
+    either = editor.success();
+    if (either.isA()) {
+      Assert.fail();
+    }
+    NodePath childPath = root.add(num);
+    editor = tree.getTreeEditor();
+    NodePath attribute = root.add(num);
+    System.out.println(attribute.toString());
+    either = editor.putAttribute(childPath, key, ByteBuffer.wrap(attribute.toString().getBytes()));
+    if (either.isA()) {
+      Assert.fail();
+    }
+    editor = either.b();
+    either = editor.success();
+  }
 }
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/query/SearchQueryTest.java	Sat Nov 15 17:48:07 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/query/SearchQueryTest.java	Sun Nov 16 06:40:48 2014 +0900
@@ -27,7 +27,7 @@
 
 public class SearchQueryTest {
 
-	@Test
+  @Test
 	public void SearchQueryTest() {
 		Jungle jungle = new DefaultJungle(null, "hogehoge",new DefaultTreeEditor(new DefaultTraverser()));
 		jungle.createNewTree("tree");
@@ -40,12 +40,16 @@
 		
 		Iterator<Pair<TreeNode, NodePath>> searchNode = ifTraverser.find(
 		        (TreeNode node) -> {
-		            ByteBuffer attribute = node.getAttributes().get(key);
-		            if(attribute != null){
+		            List<ByteBuffer> attributeList = node.getAttributes().get(key);
+		            if(attributeList.isNotEmpty()){
+		              for (ByteBuffer attribute : attributeList) {
 		                byte[] byteAttribute = attribute.array();
 		                String str = new String(byteAttribute);
 		                System.out.println("attribute = " + str);
-		                return str.equals("<-1,0,1>");
+		                if (str.equals("<-1,0,1>"))
+		                  return true;
+		                continue;
+		              }
 		            }
 		            return false;
 		        }
@@ -53,7 +57,8 @@
 		
 		
 		while (searchNode.hasNext()){
-			Assert.assertTrue(compare(searchNode.next().left(),"<-1,0,1>"));			
+		  TreeNode node = searchNode.next().left();
+			Assert.assertTrue(compare(node,"<-1,0,1>"));			
 		}
 				
 		TreeMap<String, TreeMap<String, List<NodePath>>> index = ifTraverser.getIndex();
@@ -62,51 +67,52 @@
 		TreeMap<String, List<NodePath>> innerIndex = opIndex.some();
 		Assert.assertTrue(!innerIndex.get("<-1,0,0>").isNone());
 	}
-	
-	
-	public boolean compare(TreeNode compareNode, String compareAttribute) {
-		String labName = compareNode.getAttributes().getString(key);
-		if (labName.equals(compareAttribute))
-			return true;
-		return false;
-	}
+
+  public boolean compare(TreeNode compareNode, String compareAttribute) {
+     Iterator<String> labNameIterator = compareNode.getAttributes().getString(key);
+     Assert.assertTrue(labNameIterator.hasNext());
+     String labName = labNameIterator.next(); 
+    if (labName.equals(compareAttribute))
+      return true;
+    return false;
+  }
 
-	public static String key = "KEY";
-	public static DefaultTreeNode factory = new DefaultTreeNode();
+  public static String key = "KEY";
+  public static DefaultTreeNode factory = new DefaultTreeNode();
 
-	public void createTree(JungleTree tree) {
-		NodePath root = new DefaultNodePath();
-		createChildren(tree, root, 0);
+  public void createTree(JungleTree tree) {
+    NodePath root = new DefaultNodePath();
+    createChildren(tree, root, 0);
 
-		for (int x = 0; x < 2; x++) {
-			createChildren(tree, root.add(0), x);
-			for (int y = 0; y < 2; y++) {
-				createChildren(tree, root.add(0).add(x), y);
-			}
-		}
+    for (int x = 0; x < 2; x++) {
+      createChildren(tree, root.add(0), x);
+      for (int y = 0; y < 2; y++) {
+        createChildren(tree, root.add(0).add(x), y);
+      }
+    }
 
-	}
+  }
 
-	public void createChildren(JungleTree tree, NodePath root, int num) {
-		JungleTreeEditor editor = tree.getTreeEditor();// Treeのeditorを作成
-		Either<Error, JungleTreeEditor> either = editor.addNewChildAt(root,num); // 新しく入れるところへのパス
-		if (either.isA()) {
-			Assert.fail();
-		}
-		editor = either.b();
-		either = editor.success();
-		if (either.isA()) {
-			Assert.fail();
-		}
-		NodePath childPath = root.add(num);
-		editor = tree.getTreeEditor();
-		NodePath attribute = root.add(num);
-		System.out.println(attribute.toString());
-		either = editor.putAttribute(childPath, key,ByteBuffer.wrap(attribute.toString().getBytes()));
-		if (either.isA()) {
-			Assert.fail();
-		}
-		editor = either.b();
-		either = editor.success();
-	}
+  public void createChildren(JungleTree tree, NodePath root, int num) {
+    JungleTreeEditor editor = tree.getTreeEditor();// Treeのeditorを作成
+    Either<Error, JungleTreeEditor> either = editor.addNewChildAt(root, num); // 新しく入れるところへのパス
+    if (either.isA()) {
+      Assert.fail();
+    }
+    editor = either.b();
+    either = editor.success();
+    if (either.isA()) {
+      Assert.fail();
+    }
+    NodePath childPath = root.add(num);
+    editor = tree.getTreeEditor();
+    NodePath attribute = root.add(num);
+    System.out.println(attribute.toString());
+    either = editor.putAttribute(childPath, key, ByteBuffer.wrap(attribute.toString().getBytes()));
+    if (either.isA()) {
+      Assert.fail();
+    }
+    editor = either.b();
+    either = editor.success();
+  }
 }