view src/main/java/jp/ac/u_ryukyu/ie/cr/jungle/traverser/DefaultTraverser.java @ 329:2a0cb1f0ba4e

rename Error package
author kono
date Sat, 08 Jul 2017 21:05:55 +0900
parents 20fac8350822
children
line wrap: on
line source

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

import jp.ac.u_ryukyu.ie.cr.jungle.data.list.List;
import jp.ac.u_ryukyu.ie.cr.jungle.core.Children;
import jp.ac.u_ryukyu.ie.cr.jungle.transaction.node.TreeNode;
import jp.ac.u_ryukyu.ie.cr.jungle.store.trasnformer.NodeEditorError;
import jp.ac.u_ryukyu.ie.cr.jungle.util.DefaultEither;
import jp.ac.u_ryukyu.ie.cr.jungle.util.Either;
import jp.ac.u_ryukyu.ie.cr.jungle.util.jungleError.Error;

import java.util.Iterator;


public class DefaultTraverser implements Traverser {
    @Override
    public Either<Error, Traversal> traverse(final TreeNode _root, Evaluator _evaluator) {
        Children wrapper = new Children() {
            @Override
            public Iterator<TreeNode> iterator() {
                List<TreeNode> list = new List();
                return list.addLast(_root).iterator();
            }

            @Override
            public int size() {
                return 1;
            }

            @Override
            public Either<Error, TreeNode> at(int _pos) {
                if (_pos != 0) {
                    return DefaultEither.newA(NodeEditorError.INDEX_OUT_OF_BOUNDS);
                }
                return DefaultEither.newB(_root);
            }
        };

        //Children<T> chs = _root.getChildren();
        Children chs = wrapper;

        Either<Error, List<Direction<TreeNode>>> ret = _traverse(chs, _evaluator, -1);

        if (ret.isA()) {
            return DefaultEither.newA(ret.a());
        }

        List<Direction<TreeNode>> list = ret.b();

        final Iterable<Direction<TreeNode>> iterable = list;
        final TreeNode destination = ret.b().head().getTarget();

        Traversal traversal = new Traversal() {
            @Override
            public Iterator<Direction<TreeNode>> iterator() {
                return iterable.iterator();
            }

            @Override
            public TreeNode destination() {
                return destination;
            }
        };

        return DefaultEither.newB(traversal);
    }

    private Either<Error, List<Direction<TreeNode>>> _traverse(Children _chs, Evaluator _evaluator, int _pos) {
        int pos = _pos;
        for (TreeNode ch : _chs) {
            Evaluation e = _evaluator.evaluate(ch, pos);
            Result r = e.result();
            if (r == Result.ACCEPT) {
                return _accept(ch, pos, e.evaluator());
            }

            if (r == Result.GOAL) {
                return DefaultEither.newB(_goal(ch, pos));
            }

            if (r == Result.SPECIAL) {
                return DefaultEither.newB(_goal(ch, -2));
            }

            if (r == Result.BREAK) {
                break;
            }

            if (r == Result.CONTINUE) {
                pos++;
                continue;
            }

            return DefaultEither.newA(TraverserError.UNDEFINED_OPERATOR);
        }

        return DefaultEither.newA(TraverserError.PATH_NOT_FOUND);
    }

    private List<Direction<TreeNode>> _goal(final TreeNode _current, final int _pos) {
        Direction<TreeNode> d = new Direction<TreeNode>() {
            @Override
            public int getPosition() {
                return _pos;
            }

            @Override
            public TreeNode getTarget() {
                return _current;
            }
        };

        List<Direction<TreeNode>> list = new List();
        List<Direction<TreeNode>> newList = list.addLast(d);

        return newList;
    }

    private <T extends TreeNode> Either<Error, List<Direction<TreeNode>>> _accept(final T _current, final int _pos, Evaluator _evaluator) {
        Children chs = _current.getChildren();
        Either<Error, List<Direction<TreeNode>>> either = _traverse(chs, _evaluator, 0);
        if (either.isA()) {
            return either;
        }

        List<Direction<TreeNode>> list = either.b();
        Direction<TreeNode> d = new Direction<TreeNode>() {
            @Override
            public int getPosition() {
                return _pos;
            }

            @Override
            public T getTarget() {
                return _current;
            }
        };

        List<Direction<TreeNode>> newList = list.addLast(d);
        return DefaultEither.newB(newList);
    }
}