package com.github.simy4.xpath.expr;

import com.github.simy4.xpath.XmlBuilderException;
import com.github.simy4.xpath.navigator.Navigator;
import com.github.simy4.xpath.navigator.Node;
import com.github.simy4.xpath.util.FlatteningIterator;
import com.github.simy4.xpath.util.Function;
import com.github.simy4.xpath.util.TransformingIterator;
import com.github.simy4.xpath.view.IterableNodeView;
import com.github.simy4.xpath.view.NodeSetView;
import com.github.simy4.xpath.view.NodeView;
import com.github.simy4.xpath.view.ViewContext;

import javax.annotation.Nonnull;
import java.util.Iterator;

public class DescendantOrSelfExpr extends AbstractExpr {

    @Override
    public <N extends Node> IterableNodeView<N> resolve(final ViewContext<N> context) throws XmlBuilderException {
        return new NodeSetView<N>(new Iterable<NodeView<N>>() {
            @Nonnull
            @Override
            public Iterator<NodeView<N>> iterator() {
                return new DescendantOrSelfIterator<N>(context.getNavigator(), context.getCurrent());
            }
        });
    }

    private static final class DescendantOrSelfIterator<T extends Node> implements Iterator<NodeView<T>> {

        private final Iterator<NodeView<T>> descendantOfSelf;

        private DescendantOrSelfIterator(Navigator<T> navigator, NodeView<T> self) {
            this.descendantOfSelf = new FlatteningIterator<NodeView<T>>(self.iterator(),
                    new TransformingIterator<T, Iterator<NodeView<T>>>(
                            navigator.elementsOf(self.getNode()).iterator(),
                            new DescendantOrSelf<T>(navigator)));
        }

        @Override
        public boolean hasNext() {
            return descendantOfSelf.hasNext();
        }

        @Override
        public NodeView<T> next() {
            return descendantOfSelf.next();
        }

        @Override
        public void remove() {
            descendantOfSelf.remove();
        }

    }

    private static final class DescendantOrSelf<T extends Node> implements Function<T, Iterator<NodeView<T>>> {

        private final Navigator<T> navigator;

        private DescendantOrSelf(Navigator<T> navigator) {
            this.navigator = navigator;
        }

        @Override
        public Iterator<NodeView<T>> apply(T node) {
            return new DescendantOrSelfIterator<T>(navigator, new NodeView<T>(node));
        }

    }

}

@@ -35,59 +35,8 @@
 r;%0A%0A
-import com.github.simy4.xpath.XmlBuilderException;%0A
 impo
@@ -702,35 +702,8 @@
 ext)
- throws XmlBuilderException
  %7B%0A 
@@ -877,37 +877,33 @@
          return 
-new D
+d
 escendantOrSelfI
@@ -905,19 +905,8 @@
 Self
-Iterator%3CN%3E
 (con
@@ -1005,200 +1005,63 @@
 tic 
-final class DescendantOrSelfIterator%3CT extends Node%3E implements Iterator%3CNodeView%3CT%3E%3E %7B%0A%0A        private final Iterator%3CNodeView%3CT%3E%3E descendantOfSelf;%0A%0A        private DescendantOrSelfIterator
+%3CT extends Node%3E Iterator%3CNodeView%3CT%3E%3E descendantOrSelf
 (Nav
@@ -1113,35 +1113,14 @@
     
-    this.descendantOfSelf =
+return
  new
@@ -1181,28 +1181,24 @@
             
-    
 new Transfor
@@ -1261,20 +1261,16 @@
         
-   
- 
 navigato
@@ -1330,28 +1330,24 @@
             
-    
 new Descenda
@@ -1376,338 +1376,8 @@
 ));%0A
-        %7D%0A%0A        @Override%0A        public boolean hasNext() %7B%0A            return descendantOfSelf.hasNext();%0A        %7D%0A%0A        @Override%0A        public NodeView%3CT%3E next() %7B%0A            return descendantOfSelf.next();%0A        %7D%0A%0A        @Override%0A        public void remove() %7B%0A            descendantOfSelf.remove();%0A        %7D%0A%0A
     
@@ -1739,21 +1739,17 @@
  return 
-new D
+d
 escendan
@@ -1759,19 +1759,8 @@
 Self
-Iterator%3CT%3E
 (nav

Simplify Descendant-or-self