Home | History | Annotate | Download | only in lexicalpreservation
      1 /*
      2  * Copyright (C) 2007-2010 Jlio Vilmar Gesser.
      3  * Copyright (C) 2011, 2013-2016 The JavaParser Team.
      4  *
      5  * This file is part of JavaParser.
      6  *
      7  * JavaParser can be used either under the terms of
      8  * a) the GNU Lesser General Public License as published by
      9  *     the Free Software Foundation, either version 3 of the License, or
     10  *     (at your option) any later version.
     11  * b) the terms of the Apache License
     12  *
     13  * You should have received a copy of both licenses in LICENCE.LGPL and
     14  * LICENCE.APACHE. Please refer to those files for details.
     15  *
     16  * JavaParser is distributed in the hope that it will be useful,
     17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19  * GNU Lesser General Public License for more details.
     20  */
     21 
     22 package com.github.javaparser.printer.lexicalpreservation;
     23 
     24 import java.util.Iterator;
     25 import java.util.LinkedList;
     26 import java.util.List;
     27 
     28 class TextElementIteratorsFactory {
     29 
     30     static class CascadingIterator<E> implements Iterator<E> {
     31         interface Provider<E> {
     32             Iterator<E> provide();
     33         }
     34 
     35         private final Provider<E> nextProvider;
     36         private Iterator<E> current;
     37         private Iterator<E> next;
     38         private boolean lastReturnedFromCurrent = false;
     39         private boolean lastReturnedFromNext = false;
     40 
     41         public CascadingIterator(Iterator<E> current, Provider<E> nextProvider) {
     42             this.nextProvider = nextProvider;
     43             this.current = current;
     44         }
     45 
     46 
     47         @Override
     48         public boolean hasNext() {
     49             if (current.hasNext()) {
     50                 return true;
     51             }
     52             if (next == null) {
     53                 next = nextProvider.provide();
     54             }
     55             return next.hasNext();
     56         }
     57 
     58         @Override
     59         public E next() {
     60             if (current.hasNext()) {
     61                 lastReturnedFromCurrent = true;
     62                 lastReturnedFromNext = false;
     63                 return current.next();
     64             }
     65             if (next == null) {
     66                 next = nextProvider.provide();
     67             }
     68             lastReturnedFromCurrent = false;
     69             lastReturnedFromNext = true;
     70             return next.next();
     71         }
     72 
     73         @Override
     74         public void remove() {
     75             if (lastReturnedFromCurrent) {
     76                 current.remove();
     77                 return;
     78             }
     79             if (lastReturnedFromNext) {
     80                 next.remove();
     81                 return;
     82             }
     83             throw new IllegalArgumentException();
     84         }
     85     }
     86 
     87     static class EmptyIterator<E> implements Iterator<E> {
     88         @Override
     89         public boolean hasNext() {
     90             return false;
     91         }
     92 
     93         @Override
     94         public E next() {
     95             throw new IllegalArgumentException();
     96         }
     97     }
     98 
     99     private static class SingleElementIterator<E> implements Iterator<E> {
    100         private final E element;
    101         private boolean returned;
    102 
    103         SingleElementIterator(E element) {
    104             this.element = element;
    105         }
    106 
    107         @Override
    108         public boolean hasNext() {
    109             return !returned;
    110         }
    111 
    112         @Override
    113         public E next() {
    114             returned = true;
    115             return element;
    116         }
    117 
    118         @Override
    119         public void remove() {
    120 
    121         }
    122     }
    123 
    124     static class ComposedIterator<E> implements Iterator<E> {
    125         private final List<Iterator<E>> elements;
    126         private int currIndex;
    127 
    128         ComposedIterator(List<Iterator<E>> elements) {
    129             this.elements = elements;
    130             currIndex = 0;
    131         }
    132 
    133         @Override
    134         public boolean hasNext() {
    135             if (currIndex >= elements.size()) {
    136                 return false;
    137             }
    138             if (elements.get(currIndex).hasNext()){
    139                 return true;
    140             }
    141             currIndex++;
    142             return hasNext();
    143         }
    144 
    145         @Override
    146         public E next() {
    147             if (!hasNext()) {
    148                 throw new IllegalArgumentException();
    149             }
    150             return elements.get(currIndex).next();
    151         }
    152 
    153         @Override
    154         public void remove() {
    155             elements.get(currIndex).remove();
    156         }
    157     }
    158 
    159     private static Iterator<TokenTextElement> reverseIterator(NodeText nodeText, int index) {
    160         TextElement textElement = nodeText.getTextElement(index);
    161         if (textElement instanceof TokenTextElement) {
    162             return new SingleElementIterator<TokenTextElement>((TokenTextElement)textElement) {
    163                 @Override
    164                 public void remove() {
    165                     nodeText.removeElement(index);
    166                 }
    167             };
    168         } else if (textElement instanceof ChildTextElement) {
    169             ChildTextElement childTextElement = (ChildTextElement)textElement;
    170             NodeText textForChild = childTextElement.getNodeTextForWrappedNode();
    171             return reverseIterator(textForChild);
    172         } else {
    173             throw new IllegalArgumentException();
    174         }
    175     }
    176 
    177     public static Iterator<TokenTextElement> reverseIterator(NodeText nodeText) {
    178         return partialReverseIterator(nodeText, nodeText.numberOfElements() - 1);
    179     }
    180 
    181     public static Iterator<TokenTextElement> partialReverseIterator(NodeText nodeText, int fromIndex) {
    182         List<Iterator<TokenTextElement>> elements = new LinkedList<>();
    183         for (int i=fromIndex;i>=0;i--) {
    184             elements.add(reverseIterator(nodeText, i));
    185         }
    186         return new ComposedIterator<>(elements);
    187     }
    188 
    189 }
    190