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