changeset 148:a2c374a2686b

Merge with 0854f9a9e81db5db639f02a126ebabf1d004b98e
author one
date Fri, 21 Nov 2014 12:49:28 +0900
parents af67dd0b5ba2 (current diff) 0854f9a9e81d (diff)
children 8a0aa8fc137c
files src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/DefaultJungle.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/DefaultJungleTree.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/JungleTree.java 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/store/ChangeSet.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultChangeSet.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultJungleTreeEditor.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTransactionManager.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/transaction/IndexJungleTreeEditor.java src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/TransactionManager.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/DefaultIndexEditor.java src/main/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/store/index/DeleteChildIndexEditor.java src/main/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/store/index/IndexEditor.java src/main/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/store/index/IndexManager.java src/test/java/DefaultJungleTreeTest.java src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/GetOldTreeTest.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 23 files changed, 586 insertions(+), 173 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/App.java	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/App.java	Fri Nov 21 12:49:28 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;
@@ -34,7 +35,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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/Attributes.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/TreeNodeAttributes.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/store/impl/logger/LoggingAttributes.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNode.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNodeAttribute.java	Fri Nov 21 12:49:28 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;
@@ -14,80 +16,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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/transaction/DefaultTreeNodeChildren.java	Fri Nov 21 12:49:28 2014 +0900
@@ -25,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;
@@ -47,6 +47,7 @@
 	public List<TreeNode> getChildrenAsRawList(){
 		return children;
 	}
+	
 	@Override
 	public Either<Error,TreeNode> addNewChildAt(int _pos)
 	{
@@ -106,8 +107,7 @@
 	@Override
 	public Either<Error,TreeNode> at(int _pos)
 	{
-	  System.out.println(children.length());
-    if(children.length() < _pos + 1){
+    if(!boundaryCheck(_pos + 1)){
       return DefaultEither.newA(NodeEditorError.INDEX_OUT_OF_BOUNDS);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/store/index/AddNewChildrenIndexEditor.java	Fri Nov 21 12:49:28 2014 +0900
@@ -0,0 +1,117 @@
+package jp.ac.u_ryukyu.ie.cr.tatsuki.jungle.store.index;
+
+
+import fj.Ord;
+import fj.data.List;
+import fj.data.TreeMap;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.NodePath;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.TreeEditor;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.DefaultNodePath;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNode;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.TreeOperationLog;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.IndexJungleTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.TransactionManager;
+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.Pair;
+
+public class AddNewChildrenIndexEditor implements IndexEditor {
+
+	NodePath editNodePath;
+
+	public AddNewChildrenIndexEditor(int pos, NodePath path) {
+		this.editNodePath = path.add(pos);
+	}
+
+	@Override
+	public Either<Error, IndexJungleTreeEditor> edit(
+			TreeNode root,
+			TransactionManager txManager,
+			TreeEditor editor,
+			TreeOperationLog log,
+			TreeMap<String, TreeMap<String, List<NodePath>>> index) {
+
+		TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = editIndex(index);
+		IndexJungleTreeEditor newEditor = new IndexJungleTreeEditor(root, txManager, editor, newIndex);
+		return DefaultEither.newB(newEditor);
+	}
+
+	public TreeMap<String, TreeMap<String, List<NodePath>>> editIndex(
+			TreeMap<String, TreeMap<String, List<NodePath>>> index) {
+
+		if (!index.isEmpty()) {
+			List<String> keyList = index.keys();
+			TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = TreeMap.empty(Ord.stringOrd);
+			TreeMap<String, List<NodePath>> newInnerIndex = TreeMap.empty(Ord.stringOrd);
+
+			for (String indexKey : keyList) {
+				TreeMap<String, List<NodePath>> innerIndex = index.get(indexKey).some();
+				List<String> innerIndexKeyList = innerIndex.keys();
+
+				for (String innerIndexKey : innerIndexKeyList) {
+					List<NodePath> pairList = innerIndex.get(innerIndexKey).some();
+					List<NodePath> list = checkPath(pairList);
+					if (!list.isEmpty()){
+						//System.out.println(new String(list.head().left().getAttributes().get("KEY").array()));
+						newInnerIndex = newInnerIndex.set(innerIndexKey, list);
+					}
+				}
+				newIndex = newIndex.set(indexKey, newInnerIndex);
+			}
+			return newIndex;
+		} else {
+			return index;
+		}
+	}
+
+	public List<NodePath> checkPath(List<NodePath> pairList){
+
+		List<NodePath> list = List.nil();
+		for (NodePath path : pairList) {
+
+	
+			//System.out.println("oldPath = " + path.toString());
+			NodePath newPath = new DefaultNodePath();
+			
+			
+			if (editNodePath.size() > path.size()) {
+				list = list.cons(path);
+				continue;
+			}
+
+			Pair<Integer, NodePath> editNodePathCopy = editNodePath.pop();
+			int loopCount = 0;
+
+			for (Integer pathInt : path) {
+				loopCount++;
+
+				if (pathInt == -1)
+					continue;
+				
+				if (editNodePathCopy.right().size() > 0) {
+					editNodePathCopy = editNodePathCopy.right().pop();
+					
+					if (loopCount == editNodePath.size() && editNodePathCopy.left() <= pathInt) {
+						newPath = newPath.add(pathInt + 1);
+						continue;
+					}
+
+					if (!(editNodePathCopy.left() == pathInt)) {
+						newPath = path;
+						break;
+					}
+				}
+
+				newPath = newPath.add(pathInt);
+
+			}
+
+			//System.out.println("newPath = " + newPath.toString());
+			list = list.cons(path);
+		}
+
+		return list;
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/store/index/DeleteIndexEditor.java	Fri Nov 21 12:49:28 2014 +0900
@@ -0,0 +1,107 @@
+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;
+import fj.data.TreeMap;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.NodePath;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.TreeEditor;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNode;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.TreeOperationLog;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.IndexJungleTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.TransactionManager;
+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.Pair;
+
+public class DeleteIndexEditor implements IndexEditor {
+
+	String key;
+	String pathString;
+	NodePath path;
+	TreeNode node;
+	
+	public DeleteIndexEditor(String key, NodePath path, TreeNode node) {
+		this.key = key;
+		this.pathString = path.toString();
+		this.path = path; 
+		this.node = node;
+	}
+	
+	@Override
+	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);
+		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;
+	}
+	
+	public TreeMap<String, TreeMap<String, List<NodePath>>> editIndex(String attribute, TreeMap<String, TreeMap<String, List<NodePath>>> index){
+	
+		Option<TreeMap<String, List<NodePath>>> innerIndexOp = index.get(key);
+		
+		if (innerIndexOp.isSome()) {
+			TreeMap<String, List<NodePath>> innerIndex = innerIndexOp.some();
+			Option<List<NodePath>> listOp = innerIndex.get(attribute);
+			
+			if (listOp.isSome()) {
+				List<NodePath> list = listOp.some();
+				List<NodePath> newList = List.nil();
+				
+				for (NodePath path : list){
+					if (!path.toString().equals(pathString)) {
+						newList = newList.cons(path);
+					}
+				}
+				
+				if (newList.isEmpty()) {
+					TreeMap<String, List<NodePath>> newInnerIndex = innerIndex.delete(attribute);
+					
+					if (newInnerIndex.isEmpty()) {
+						TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = index.delete(key);
+						return newIndex;	
+					}
+					
+					TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = index.set(key, newInnerIndex);
+					return newIndex;
+				}
+					
+				TreeMap<String, List<NodePath>> newInnerIndex = innerIndex.set(attribute,newList);
+				TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = index.set(key, newInnerIndex);
+				return newIndex;
+				
+			} else {
+				return index;
+			}
+		} else {
+			return index;
+		}
+	}
+
+	public TreeNode getTarget(TreeNode node , NodePath path){
+		Pair<Integer, NodePath> pathNode = path.pop();
+		Either<Error, TreeNode> either = node.getChildren().at(pathNode.left());
+		if (either.isA())
+			return node;
+		
+		TreeNode child = either.b();
+		if (pathNode.right().size() == 0)
+			return child;
+		
+		TreeNode target = getTarget(child,pathNode.right());
+		return target;
+	}
+
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/jp/ac/u_ryukyu/ie/cr/tatsuki/jungle/store/index/PutIndexEditor.java	Fri Nov 21 12:49:28 2014 +0900
@@ -0,0 +1,98 @@
+package jp.ac.u_ryukyu.ie.cr.tatsuki.jungle.store.index;
+
+
+
+import fj.Ord;
+import fj.data.List;
+import fj.data.Option;
+import fj.data.TreeMap;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.NodePath;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.TreeEditor;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.TreeNode;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.store.impl.logger.TreeOperationLog;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.IndexJungleTreeEditor;
+import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.transaction.TransactionManager;
+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 java.nio.ByteBuffer;
+
+public class PutIndexEditor implements IndexEditor {
+
+	String key; 
+	String attribute;
+	NodePath path;
+	TransactionManager txManager;
+	TreeNode root;
+	TreeEditor editor;
+	TreeOperationLog log;
+	
+	public PutIndexEditor(String key, ByteBuffer attribute,NodePath path) {
+	    this.key = key;
+	    this.attribute = new String(attribute.array());
+	    this.path = path;
+	}
+
+	@Override
+	public Either<Error, IndexJungleTreeEditor> edit(TreeNode root,TransactionManager txManager,TreeEditor editor,TreeOperationLog log,TreeMap<String, TreeMap<String, List<NodePath>>> index) {
+		TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = editIndex(path, key, attribute,index);
+		IndexJungleTreeEditor newEditor = new IndexJungleTreeEditor(root,txManager,editor,log, newIndex);
+		Either<Error, IndexJungleTreeEditor> either = DefaultEither.newB(newEditor);
+		return either;
+	}
+	
+	public TreeMap<String, TreeMap<String, List<NodePath>>> editIndex(NodePath path, String key, String attribute,TreeMap<String, TreeMap<String, List<NodePath>>> index){
+
+		Option<TreeMap<String, List<NodePath>>> innerIndexOp = index.get(key); 
+		
+		if (attribute != null) {
+			if (innerIndexOp.isNone()) {
+
+				TreeMap<String, List<NodePath>> innerIndex = TreeMap.empty(Ord.stringOrd);
+				List<NodePath> list = List.nil();
+				list = list.cons(path);
+				innerIndex = innerIndex.set(attribute, list);
+				TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = index.set(key, innerIndex);
+				return newIndex;
+			} else {
+
+				TreeMap<String, List<NodePath>> innerIndex = innerIndexOp.some();
+				
+				Option<List<NodePath>> opList = innerIndex.get(attribute);
+
+				if (opList.isNone()) {
+
+					List<NodePath> list = List.nil();
+					list = list.cons(path);
+					innerIndex = innerIndex.set(attribute, list);
+
+				} else {
+
+					List<NodePath> list = opList.some();
+					list = list.cons(path);
+					innerIndex = innerIndex.set(attribute, list);
+
+				}
+				TreeMap<String, TreeMap<String, List<NodePath>>> newIndex = index.set(key, innerIndex);
+				return newIndex;
+			}
+		}
+		return index;
+	}
+	
+//	public TreeNode getTarget(TreeNode node , NodePath path){
+//		Pair<Integer, NodePath> path = path.pop();
+//		Either<Error, TreeNode> either = node.getChildren().at(path.left());
+//		if (either.isA())
+//			return node;
+//		
+//		TreeNode child = either.b();
+//		if (path.right().size() == 0)
+//			return child;
+//		
+//		TreeNode target = getTarget(child,path.right());
+//		return target;
+//	}
+
+}
--- a/src/test/java/DefaultJungleTreeTest.java	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/DefaultJungleTreeTest.java	Fri Nov 21 12:49:28 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;
@@ -46,7 +47,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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/AttributesTest.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/GetOldTreeTest.java	Fri Nov 21 12:49:28 2014 +0900
@@ -2,6 +2,7 @@
 
 
 import java.nio.ByteBuffer;
+import java.util.Iterator;
 
 import org.junit.Test;
 
@@ -35,13 +36,37 @@
       Assert.assertFalse(successEither.isA());
       editor = successEither.b();
     }
-    System.out.println(tree.revision());
+
+    JungleTreeEditor newEditor = tree.getTreeEditor();
+    JungleTreeEditor newPutEditor = newEditor.putAttribute(path.add(9), "test", ByteBuffer.wrap("kanagawa".getBytes())).b();
+    newPutEditor.success();
+    
     TreeNode root = tree.getRootNode();
-    Assert.assertTrue(root.getChildren().at(9).isB());
+    Either<Error, TreeNode> childNodeEither = root.getChildren().at(9);
+    Assert.assertTrue(childNodeEither.isB());
+    TreeNode child = childNodeEither.b();
+    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();
     
-    JungleTree oldTree = tree.getOldTree(9).b();
-    System.out.println(oldTree.revision());
-    TreeNode oldRoot = oldTree.getRootNode();
-    Assert.assertTrue(oldRoot.getChildren().at(9).isA());
+    TreeNode oldRoot1 = oldTree1.getRootNode();
+    Either<Error, TreeNode> oldChildNodeEither = oldRoot1.getChildren().at(9);
+    Assert.assertTrue(oldChildNodeEither.isB());
+    
+    TreeNode oldChildNode = oldChildNodeEither.b();
+    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();
+    TreeNode oldRoot2 = oldTree2.getRootNode();
+    Assert.assertTrue(oldRoot2.getChildren().at(9).isA());
+    
+    
   }
 }
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/impl/treeeditor/DefaultTreeEditorTest.java	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/impl/treeeditor/DefaultTreeEditorTest.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/nodeeditor/DeleteAttributeAtTest.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/core/nodeeditor/PutAttributeTest.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/clonable/DefaultTreeNodeAttributesTest.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultAttributesTest.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultChildrenTest.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/impl/node/DefaultNodeTest.java	Fri Nov 21 12:49:28 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	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/traverse/TraverserTest.java	Fri Nov 21 12:49:28 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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/functionaljava/FjListTest.java	Fri Nov 21 12:49:28 2014 +0900
@@ -0,0 +1,20 @@
+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();
+    boolean t1 = list.isEmpty();
+    list = list.tail();
+    boolean t2 = list.isEmpty();
+    System.out.println(aaa);
+  }
+}
--- a/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/query/SearchQueryTest.java	Fri Nov 21 12:46:36 2014 +0900
+++ b/src/test/java/jp/ac/u_ryukyu/ie/cr/tatsuki/query/SearchQueryTest.java	Fri Nov 21 12:49:28 2014 +0900
@@ -1,11 +1,9 @@
 package jp.ac.u_ryukyu.ie.cr.tatsuki.query;
 
 import java.nio.ByteBuffer;
-import java.security.KeyStore.Entry.Attribute;
 import java.util.Iterator;
 
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.DefaultJungle;
-import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.DefaultJungleTree;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.Jungle;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTree;
 import jp.ac.u_ryukyu.ie.cr.shoshi.jungle.JungleTreeEditor;
@@ -20,7 +18,6 @@
 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.Pair;
-import jp.ac.u_ryukyu.ie.cr.tatsuki.jungle.query.PathNodeIndexIterator;
 
 import org.junit.Assert;
 import org.junit.Test;
@@ -31,7 +28,7 @@
 
 public class SearchQueryTest {
 
-	@Test
+  @Test
 	public void SearchQueryTest() {
 		Jungle jungle = new DefaultJungle(null, "hogehoge",new DefaultTraverser());
 		jungle.createNewTree("tree");
@@ -39,17 +36,21 @@
 		createTree(tree);
 		tree.getRootNode();
 		InterfaceTraverser ifTraverser = tree.getTraverser();
-		TreeMap<String, TreeMap<String, List<Pair<TreeNode, NodePath>>>> cheackIndex = ifTraverser.getIndex();
+		TreeMap<String, TreeMap<String, List< NodePath>>> cheackIndex = ifTraverser.getIndex();
 		Assert.assertTrue(cheackIndex.isEmpty());
 		
 		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;
 		        }
@@ -57,60 +58,62 @@
 		
 		
 		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<Pair<TreeNode, NodePath>>>> index = ifTraverser.getIndex();
-		Option<TreeMap<String, List<Pair<TreeNode, NodePath>>>> opIndex = index.get(key);
+		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<Pair<TreeNode, NodePath>>> innerIndex = opIndex.some();
+		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 static String key = "KEY";
-	public static DefaultTreeNode factory = new DefaultTreeNode();
-
-	public void createTree(JungleTree tree) {
-		NodePath root = new DefaultNodePath();
-		createChildren(tree, root, 0);
+  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;
+  }
 
-		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 static String key = "KEY";
+  public static DefaultTreeNode factory = new DefaultTreeNode();
+
+  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();
+  }
 }