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