view src/main/java/jp/ac/u_ryukyu/ie/cr/shoshi/jungle/traverser/InterfaceTraverser.java @ 151:d9fbddf77bf6

add class Index
author one
date Sat, 22 Nov 2014 14:46:44 +0900
parents 371b6ddb78f2
children 8a0aa8fc137c
line wrap: on
line source

package jp.ac.u_ryukyu.ie.cr.shoshi.jungle.traverser;

import java.util.Iterator;

import fj.Ord;
import fj.P2;
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.NulIterator;
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.util.Pair;
import jp.ac.u_ryukyu.ie.cr.tatsuki.jungle.query.PathNodeIterator;
import jp.ac.u_ryukyu.ie.cr.tatsuki.jungle.query.Query;
import jp.ac.u_ryukyu.ie.cr.tatsuki.jungle.store.index.Index;
import jp.ac.u_ryukyu.ie.cr.tatsuki.jungle.store.index.IndexManager;

public class InterfaceTraverser {

  // InterfaceTraverser traverser;
  TreeNode node;
  Index index;
  IndexManager indexManager;

  public InterfaceTraverser(TreeNode _root, IndexManager indexManager) {
    this.node = _root;
    this.index = new Index();
    this.indexManager = indexManager;
  }

  public InterfaceTraverser(TreeNode _root, Index  index,
      IndexManager indexManager) {
    this.node = _root;
    this.index = index;
    this.indexManager = indexManager;
  }

  public void commitIndex() {
    indexManager.commit(index);
  }

  public Index getIndex() {
    return index;
  }

  public void setIndex(Index index) {
    this.index = index;
  }

  /**
   * subTree以下のNodeに対してKey,Valueのペアでindexを使って探索を行う
   * 
   * @param query
   * @param subTree
   * @param key
   * @param searchValue
   * @return
   */
  public Iterator<Pair<TreeNode, NodePath>> findInSubTree(Query query, Pair<TreeNode, NodePath> subTree, String key,
      String searchValue) {
    /*
     * indexを使って取ってきたNodeのPathと、subTreeのPathを先頭から1つずつ比較し、
     * indexから取ってきたNodeのPathが一致した場合、そのNodeを返す
     */

    if (index.get(key).isSome()) {

      TreeMap<String, List<Pair<TreeNode, NodePath>>> innerIndex = this.index.get(key).some();

      Option<List<Pair<TreeNode, NodePath>>> opList = innerIndex.get(searchValue);

      if (opList.isNone())
        return new NulIterator<Pair<TreeNode, NodePath>>();// 空のIteratorを返す

      List<Pair<TreeNode, NodePath>> list = opList.some();
      NodePath targetNodePath = subTree.right();
      List<Pair<TreeNode, NodePath>> filteredList = List.nil();

      for (Pair<TreeNode, NodePath> pair : list) {
        NodePath compareNodePath = pair.right();
        if (targetNodePath.compare(compareNodePath))
          filteredList = filteredList.cons(pair);
      }

      return filteredList.iterator();

    } else {
      final PathNodeIterator itNode = new PathNodeIterator(subTree);
      return new Iterator<Pair<TreeNode, NodePath>>() {

        private Pair<TreeNode, NodePath> matchPair = nextmatch(itNode);

        private Pair<TreeNode, NodePath> nextmatch(PathNodeIterator itNode) {

          for (; itNode.hasNext();) {
            Pair<TreeNode, NodePath> pathNode = itNode.next();
            if (query.condition(pathNode.left()))
              return pathNode;
          }
          return null;
        }

        @Override
        public boolean hasNext() {
          if (matchPair == null) {
            return false;
          }
          return true;
        }

        @Override
        public Pair<TreeNode, NodePath> next() {
          Pair<TreeNode, NodePath> currentPair = matchPair;
          matchPair = nextmatch(itNode);
          return currentPair;
        }

        @Override
        public void remove() {
        }

      };
    }
  }

  /**
   * subTree以下のNodeに対してKeyに対応する値をindexを使って探索する
   * 
   * @param query
   * @param subTree
   * @param key
   * @param searchValue
   * @return
   */
  public Iterator<Pair<TreeNode, NodePath>> findInSubTreeAllValue(Query query, Pair<TreeNode, NodePath> subTree,
      String key) {
    /*
     * indexからinnerIndexを取得 取得したinnerIndexが保有するKeyを取得
     * そのKeyを保有するNodeとNodeのPathを取得する
     * indexを使って取ってきたNodeのPathと、subTreeのPathを先頭から1つずつ比較し、
     * indexから取ってきたNodeのPathが一致した場合、そのNodeを返す
     */

    if (index.get(key).isSome()) {

      TreeMap<String, List<Pair<TreeNode, NodePath>>> innerIndex = this.index.get(key).some();
      List<String> searchValues = innerIndex.keys();
      List<Pair<TreeNode, NodePath>> filteredList = List.nil();
      NodePath targetNodePath = subTree.right();

      for (String searchValue : searchValues) {
        Option<List<Pair<TreeNode, NodePath>>> opList = innerIndex.get(searchValue);

        if (opList.isNone())
          continue;

        List<Pair<TreeNode, NodePath>> list = opList.some();
        for (Pair<TreeNode, NodePath> pair : list) {
          NodePath compareNodePath = pair.right();
          if (targetNodePath.compare(compareNodePath))
            filteredList = filteredList.cons(pair);

        }
      }
      return filteredList.iterator();

    } else {
      final PathNodeIterator itNode = new PathNodeIterator(subTree);
      return new Iterator<Pair<TreeNode, NodePath>>() {

        private Pair<TreeNode, NodePath> matchPair = nextmatch(itNode);

        private Pair<TreeNode, NodePath> nextmatch(PathNodeIterator itNode) {

          for (; itNode.hasNext();) {
            Pair<TreeNode, NodePath> pathNode = itNode.next();
            if (query.condition(pathNode.left()))
              return pathNode;
          }
          return null;
        }

        @Override
        public boolean hasNext() {
          if (matchPair == null) {
            return false;
          }
          return true;
        }

        @Override
        public Pair<TreeNode, NodePath> next() {
          Pair<TreeNode, NodePath> currentPair = matchPair;
          matchPair = nextmatch(itNode);
          return currentPair;
        }

        @Override
        public void remove() {
        }

      };
    }
  }

  public Iterator<Pair<TreeNode, NodePath>> find(Query query, String key, String searchValue) {

    if (index.get(key).isSome()) {

      TreeMap<String, List<Pair<TreeNode, NodePath>>> innerIndex = this.index.get(key).some();
      Option<List<Pair<TreeNode, NodePath>>> opList = innerIndex.get(searchValue);

      if (opList.isNone())
        return new NulIterator<Pair<TreeNode, NodePath>>();// 空のIteratorを返す

      final List<Pair<TreeNode, NodePath>> list = opList.some();
      return list.iterator();

    } else {
      Pair<TreeNode, NodePath> pair = new Pair<TreeNode, NodePath>(node, new DefaultNodePath());
      final PathNodeIterator itNode = new PathNodeIterator(pair);
      return new Iterator<Pair<TreeNode, NodePath>>() {

        private Pair<TreeNode, NodePath> matchPair = nextmatch(itNode);

        private Pair<TreeNode, NodePath> nextmatch(PathNodeIterator itNode) {

          for (; itNode.hasNext();) {
            Pair<TreeNode, NodePath> pathNode = itNode.next();
            String value = pathNode.left().getAttributes().getString(key);
            Option<TreeMap<String, List<Pair<TreeNode, NodePath>>>> innerIndexOp = index.get(key);

            if (value != null) {
              if (innerIndexOp.isNone()) {

                TreeMap<String, List<Pair<TreeNode, NodePath>>> innerIndex = TreeMap.empty(Ord.stringOrd);
                List<Pair<TreeNode, NodePath>> list = List.nil();
                list = list.cons(pathNode);
                innerIndex = innerIndex.set(value, list);
                index = index.set(key, innerIndex);

              } else {

                TreeMap<String, List<Pair<TreeNode, NodePath>>> innerIndex = innerIndexOp.some();
                Option<List<Pair<TreeNode, NodePath>>> opList = innerIndex.get(value);

                if (opList.isNone()) {

                  List<Pair<TreeNode, NodePath>> list = List.nil();
                  list = list.cons(pathNode);
                  innerIndex = innerIndex.set(value, list);

                } else {

                  List<Pair<TreeNode, NodePath>> list = opList.some();
                  list = list.cons(pathNode);
                  innerIndex = innerIndex.set(value, list);

                }
                index = index.set(key, innerIndex);

              }
            }

            if (query.condition(pathNode.left()))
              return pathNode;
          }
          return null;
        }

        @Override
        public boolean hasNext() {
          if (matchPair == null) {
            // index = itNode.getIndex();
            return false;
          }
          return true;
        }

        @Override
        public Pair<TreeNode, NodePath> next() {
          Pair<TreeNode, NodePath> currentPair = matchPair;
          matchPair = nextmatch(itNode);
          return currentPair;
        }

        @Override
        public void remove() {
        }

      };
    }
  }

  public Iterator<Pair<TreeNode, NodePath>> findAll(Query query, String key) {

    if (index.get(key).isSome()) {

      TreeMap<String, List<Pair<TreeNode, NodePath>>> innerIndex = this.index.get(key).some();
      List<String> searchValues = innerIndex.keys();
      List<Pair<TreeNode, NodePath>> valueList = List.nil();

      for (String searchValue : searchValues) {
        Option<List<Pair<TreeNode, NodePath>>> opList = innerIndex.get(searchValue);

        if (opList.isNone())
          continue;

        List<Pair<TreeNode, NodePath>> list = opList.some();
        valueList = valueList.append(list);
      }
      return valueList.iterator();

    } else {
      Pair<TreeNode, NodePath> pair = new Pair<TreeNode, NodePath>(node, new DefaultNodePath());
      final PathNodeIterator itNode = new PathNodeIterator(pair);
      return new Iterator<Pair<TreeNode, NodePath>>() {

        private Pair<TreeNode, NodePath> matchPair = nextmatch(itNode);

        private Pair<TreeNode, NodePath> nextmatch(PathNodeIterator itNode) {

          for (; itNode.hasNext();) {
            Pair<TreeNode, NodePath> pathNode = itNode.next();
            String value = pathNode.left().getAttributes().getString(key);
            Option<TreeMap<String, List<Pair<TreeNode, NodePath>>>> innerIndexOp = index.get(key);

            if (value != null) {
              if (innerIndexOp.isNone()) {

                TreeMap<String, List<Pair<TreeNode, NodePath>>> innerIndex = TreeMap.empty(Ord.stringOrd);
                List<Pair<TreeNode, NodePath>> list = List.nil();
                list = list.cons(pathNode);
                innerIndex = innerIndex.set(value, list);
                index = index.set(key, innerIndex);

              } else {

                TreeMap<String, List<Pair<TreeNode, NodePath>>> innerIndex = innerIndexOp.some();
                Option<List<Pair<TreeNode, NodePath>>> opList = innerIndex.get(value);

                if (opList.isNone()) {

                  List<Pair<TreeNode, NodePath>> list = List.nil();
                  list = list.cons(pathNode);
                  innerIndex = innerIndex.set(value, list);

                } else {

                  List<Pair<TreeNode, NodePath>> list = opList.some();
                  list = list.cons(pathNode);
                  innerIndex = innerIndex.set(value, list);

                }
                index = index.set(key, innerIndex);

              }
            }

            if (query.condition(pathNode.left()))
              return pathNode;
          }
          return null;
        }

        @Override
        public boolean hasNext() {
          if (matchPair == null) {
            // index = itNode.getIndex();
            return false;
          }
          return true;
        }

        @Override
        public Pair<TreeNode, NodePath> next() {
          Pair<TreeNode, NodePath> currentPair = matchPair;
          matchPair = nextmatch(itNode);
          return currentPair;
        }

        @Override
        public void remove() {
        }

      };
    }
  }
}