176f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti/*
276f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
376f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * Copyright (C) 2011, 2013-2016 The JavaParser Team.
476f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti *
576f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * This file is part of JavaParser.
676f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti *
776f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * JavaParser can be used either under the terms of
876f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * a) the GNU Lesser General Public License as published by
976f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti *     the Free Software Foundation, either version 3 of the License, or
1076f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti *     (at your option) any later version.
1176f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * b) the terms of the Apache License
1276f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti *
1376f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * You should have received a copy of both licenses in LICENCE.LGPL and
1476f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * LICENCE.APACHE. Please refer to those files for details.
1576f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti *
1676f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * JavaParser is distributed in the hope that it will be useful,
1776f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * but WITHOUT ANY WARRANTY; without even the implied warranty of
1876f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1976f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti * GNU Lesser General Public License for more details.
2076f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti */
2176f5dc9d043237e8ada0e6597d6c8d48b67f6d8fFederico Tomassetti
22515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggenpackage com.github.javaparser.ast;
23515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
24db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggenimport com.github.javaparser.HasParentNode;
250f8bbe61c2d7132846b8ad13804ae70d62c5c8bcDanny van Bruggenimport com.github.javaparser.ast.observer.AstObserver;
260f8bbe61c2d7132846b8ad13804ae70d62c5c8bcDanny van Bruggenimport com.github.javaparser.ast.observer.Observable;
27515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggenimport com.github.javaparser.ast.visitor.GenericVisitor;
28008b82d149685d6702a060fbecafc8fc2e10b459Cruz Maximilienimport com.github.javaparser.ast.visitor.Visitable;
29515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggenimport com.github.javaparser.ast.visitor.VoidVisitor;
302adf38a7f2ee394f648d2fe7fc3e9b25810cde9dDanny van Bruggenimport com.github.javaparser.metamodel.InternalProperty;
31515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
326d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassettiimport java.util.*;
33c9f2a4fe27453e09a268730cd0ab76a42016475fDanny van Bruggenimport java.util.function.*;
34c9f2a4fe27453e09a268730cd0ab76a42016475fDanny van Bruggenimport java.util.stream.Collector;
353b31ef89fd3f2963c2bf53655f42ed459376e879Danny van Bruggenimport java.util.stream.Collectors;
366d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassettiimport java.util.stream.Stream;
376d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti
38515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen/**
39db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen * A list of nodes.
409dfe6cb2a1115f749a6a9adca05297d6b24eb046Danny van Bruggen * It usually has a parent node.
4115c2aa05f936720e8f7efdedbbc68450a6f27fb3Danny van Bruggen * Unlike normal Nodes, this does not mean that it is a child of that parent.
429dfe6cb2a1115f749a6a9adca05297d6b24eb046Danny van Bruggen * Instead, this list will make every node it contains a child of its parent.
439dfe6cb2a1115f749a6a9adca05297d6b24eb046Danny van Bruggen * This way, a NodeList does not create an extra level inside the AST.
44515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen *
45515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen * @param <N> the type of nodes contained.
46515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen */
47c77e046d2a645bf42f9450bd293e0ba69300a309Federico Tomassettipublic class NodeList<N extends Node> implements List<N>, Iterable<N>, HasParentNode<NodeList<N>>, Visitable, Observable {
482adf38a7f2ee394f648d2fe7fc3e9b25810cde9dDanny van Bruggen    @InternalProperty
49515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    private List<N> innerList = new ArrayList<>(0);
50515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
51db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    private Node parentNode;
52db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen
53263cf50ac27714b8e120565f45a1fac661df18b5Federico Tomassetti    private List<AstObserver> observers = new ArrayList<>();
546d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti
55515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public NodeList() {
5673fcc27d049a401ac87cc945bff7c0ebd8a2c9cdDanny van Bruggen        parentNode = null;
57515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
58515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
59e4c3401bc94a4d77244d346491fbe6d59347f305Danny van Bruggen    public NodeList(Collection<N> n) {
60796e7f15567eeeef96e224d8d00c27fdf1248413Danny van Bruggen        this.addAll(n);
61796e7f15567eeeef96e224d8d00c27fdf1248413Danny van Bruggen    }
62796e7f15567eeeef96e224d8d00c27fdf1248413Danny van Bruggen
63e4c3401bc94a4d77244d346491fbe6d59347f305Danny van Bruggen    public NodeList(N... n) {
64e4c3401bc94a4d77244d346491fbe6d59347f305Danny van Bruggen        this.addAll(Arrays.asList(n));
65e4c3401bc94a4d77244d346491fbe6d59347f305Danny van Bruggen    }
66e4c3401bc94a4d77244d346491fbe6d59347f305Danny van Bruggen
67f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
68f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public boolean add(N node) {
696d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti        notifyElementAdded(innerList.size(), node);
70515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        own(node);
71f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.add(node);
72515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
73515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
74515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    private void own(N node) {
75515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        if (node == null) {
76515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen            return;
77515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        }
78515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        setAsParentNodeOf(node);
79515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
80515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
81515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public boolean remove(Node node) {
82c0e1f8e102a33dc34c41318ba55469516fff0993Federico Tomassetti        int index = innerList.indexOf(node);
83c0e1f8e102a33dc34c41318ba55469516fff0993Federico Tomassetti        if (index != -1) {
84c0e1f8e102a33dc34c41318ba55469516fff0993Federico Tomassetti            notifyElementRemoved(index, node);
85c0e1f8e102a33dc34c41318ba55469516fff0993Federico Tomassetti            node.setParentNode(null);
86c0e1f8e102a33dc34c41318ba55469516fff0993Federico Tomassetti        }
879dfe6cb2a1115f749a6a9adca05297d6b24eb046Danny van Bruggen        return innerList.remove(node);
88515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
89515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
90e217cb36a3454afa75a14896f5cd85fb1c0d83f6stephenramthun    public N removeFirst() {
91e217cb36a3454afa75a14896f5cd85fb1c0d83f6stephenramthun        return remove(0);
92ae442842668f9414f3a5fd8a294968d7cddf147fstephenramthun    }
93ae442842668f9414f3a5fd8a294968d7cddf147fstephenramthun
94e217cb36a3454afa75a14896f5cd85fb1c0d83f6stephenramthun    public N removeLast() {
95e217cb36a3454afa75a14896f5cd85fb1c0d83f6stephenramthun        return remove(innerList.size() - 1);
96ae442842668f9414f3a5fd8a294968d7cddf147fstephenramthun    }
97ae442842668f9414f3a5fd8a294968d7cddf147fstephenramthun
989dfe6cb2a1115f749a6a9adca05297d6b24eb046Danny van Bruggen    @SafeVarargs
99515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public static <X extends Node> NodeList<X> nodeList(X... nodes) {
100515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        final NodeList<X> nodeList = new NodeList<>();
1019dfe6cb2a1115f749a6a9adca05297d6b24eb046Danny van Bruggen        Collections.addAll(nodeList, nodes);
102515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        return nodeList;
103515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
104515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
105515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public static <X extends Node> NodeList<X> nodeList(Collection<X> nodes) {
106515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        final NodeList<X> nodeList = new NodeList<>();
107c3f372b0c7c8ca4bed1261e7f1d3f17ed01b4889Danny van Bruggen        nodeList.addAll(nodes);
108515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        return nodeList;
109515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
110515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
111515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public static <X extends Node> NodeList<X> nodeList(NodeList<X> nodes) {
112515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        final NodeList<X> nodeList = new NodeList<>();
1139dfe6cb2a1115f749a6a9adca05297d6b24eb046Danny van Bruggen        nodeList.addAll(nodes);
114515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        return nodeList;
115515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
116515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
117515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public boolean contains(N node) {
118515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        return innerList.contains(node);
119515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
120515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
121f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
122515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public int size() {
123515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        return innerList.size();
124515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
125515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
126f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
127515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public N get(int i) {
128515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        return innerList.get(i);
129515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
130515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
131515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    @Override
132515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public Iterator<N> iterator() {
133515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        // TODO take care of "Iterator.remove"
134515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        return innerList.iterator();
135515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
136515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
137f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
138f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public N set(int index, N element) {
139f596b70f4d1995058df4dd393e1611c9418fb2d6Federico Tomassetti        if (index < 0 || index >= innerList.size()) {
140f596b70f4d1995058df4dd393e1611c9418fb2d6Federico Tomassetti            throw new IllegalArgumentException("Illegal index. The index should be between 0 and " + innerList.size()
141f596b70f4d1995058df4dd393e1611c9418fb2d6Federico Tomassetti                    + " excluded. It is instead " + index);
142f596b70f4d1995058df4dd393e1611c9418fb2d6Federico Tomassetti        }
143f596b70f4d1995058df4dd393e1611c9418fb2d6Federico Tomassetti        if (element == innerList.get(index)) {
144f596b70f4d1995058df4dd393e1611c9418fb2d6Federico Tomassetti            return element;
145f596b70f4d1995058df4dd393e1611c9418fb2d6Federico Tomassetti        }
1460d8f8e5cc0e48d0cc27cf070155ab318fe160a00Federico Tomassetti        notifyElementReplaced(index, element);
147fe3a4f32bc49f09a57dc3027a2e68182da7734fcDanny van Bruggen        innerList.get(index).setParentNode(null);
148515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        setAsParentNodeOf(element);
149f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.set(index, element);
150515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
151515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
152f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
153f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public N remove(int index) {
154263cf50ac27714b8e120565f45a1fac661df18b5Federico Tomassetti        notifyElementRemoved(index, innerList.get(index));
155f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        N remove = innerList.remove(index);
156f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        if (remove != null)
157f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien            remove.setParentNode(null);
158f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return remove;
159515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
160515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
161f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
162515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public boolean isEmpty() {
163515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        return innerList.isEmpty();
164515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
165515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
166f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
167515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public void sort(Comparator<? super N> comparator) {
168c3f372b0c7c8ca4bed1261e7f1d3f17ed01b4889Danny van Bruggen        innerList.sort(comparator);
169515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
170515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
171515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    public void addAll(NodeList<N> otherList) {
172515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        for (N node : otherList) {
173515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen            add(node);
174515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        }
175515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
176515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen
177f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
178f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public void add(int index, N node) {
1796d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti        notifyElementAdded(index, node);
180515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        own(node);
181515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen        innerList.add(index, node);
182515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen    }
183db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen
18433115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen    /**
18533115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     * Inserts the node before all other nodes.
18633115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     */
187dd34bf7240d5269586b601e76a8735629d90d5aaDanny van Bruggen    public NodeList<N> addFirst(N node) {
18833115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        add(0, node);
18933115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        return this;
19033115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen    }
19133115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen
19233115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen    /**
19333115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     * Inserts the node after all other nodes. (This is simply an alias for add.)
19433115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     */
195dd34bf7240d5269586b601e76a8735629d90d5aaDanny van Bruggen    public NodeList<N> addLast(N node) {
19633115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        add(node);
19733115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        return this;
19833115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen    }
19933115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen
20033115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen    /**
20133115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     * Inserts the node after afterThisNode.
20233115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     *
20333115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     * @throws IllegalArgumentException when afterThisNode is not in this list.
20433115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     */
20533115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen    public NodeList<N> addAfter(N node, N afterThisNode) {
20633115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        int i = indexOf(afterThisNode);
20733115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        if (i == -1) {
20833115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen            throw new IllegalArgumentException("Can't find node to insert after.");
20933115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        }
21033115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        add(i + 1, node);
21133115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        return this;
21233115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen    }
21333115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen
21433115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen    /**
21533115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     * Inserts the node before beforeThisNode.
21633115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     *
21733115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     * @throws IllegalArgumentException when beforeThisNode is not in this list.
21833115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen     */
21933115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen    public NodeList<N> addBefore(N node, N beforeThisNode) {
22033115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        int i = indexOf(beforeThisNode);
22133115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        if (i == -1) {
22233115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen            throw new IllegalArgumentException("Can't find node to insert before.");
22333115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        }
22433115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        add(i, node);
22533115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen        return this;
22633115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen    }
22733115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen
22833115b3c857a87e398e9eaffd3d29c47804a0a53Danny van Bruggen
229db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    @Override
230008b82d149685d6702a060fbecafc8fc2e10b459Cruz Maximilien    public Optional<Node> getParentNode() {
231008b82d149685d6702a060fbecafc8fc2e10b459Cruz Maximilien        return Optional.ofNullable(parentNode);
232db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    }
233db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen
234008b82d149685d6702a060fbecafc8fc2e10b459Cruz Maximilien    /**
235008b82d149685d6702a060fbecafc8fc2e10b459Cruz Maximilien     * Sets the parentNode
2364296abb695b767f7471dd255d0679516183b062aDanny van Bruggen     *
237008b82d149685d6702a060fbecafc8fc2e10b459Cruz Maximilien     * @param parentNode the parentNode
238008b82d149685d6702a060fbecafc8fc2e10b459Cruz Maximilien     * @return this, the NodeList
239008b82d149685d6702a060fbecafc8fc2e10b459Cruz Maximilien     */
240db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    @Override
241db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    public NodeList<N> setParentNode(Node parentNode) {
242db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen        this.parentNode = parentNode;
243db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen        setAsParentNodeOf(innerList);
244db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen        return this;
245db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    }
246db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen
247db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    @Override
248db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    public Node getParentNodeForChildren() {
249db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen        return parentNode;
250db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    }
251db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen
252008b82d149685d6702a060fbecafc8fc2e10b459Cruz Maximilien    @Override
253db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    public <R, A> R accept(final GenericVisitor<R, A> v, final A arg) {
254db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen        return v.visit(this, arg);
255db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    }
256db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen
257008b82d149685d6702a060fbecafc8fc2e10b459Cruz Maximilien    @Override
258db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    public <A> void accept(final VoidVisitor<A> v, final A arg) {
259db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen        v.visit(this, arg);
260db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen    }
261db52836b6a33c9ff130d8ea554f78b21ebe9b586Danny van Bruggen
262f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
263f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.lang.Iterable#forEach(java.util.function.Consumer)
264f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
265f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
266f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public void forEach(Consumer<? super N> action) {
267f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        innerList.forEach(action);
268f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
269f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
270f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
271f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#contains(java.lang.Object)
272f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
273f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
274f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public boolean contains(Object o) {
275f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.contains(o);
276f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
277f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
278f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
279f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#toArray()
280f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
281f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
282f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public Object[] toArray() {
283f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.toArray();
284f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
285f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
286f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
287f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#toArray(java.lang.Object[])
288f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
289f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
290f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public <T> T[] toArray(T[] a) {
291f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.toArray(a);
292f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
293f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
294f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
295f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#remove(java.lang.Object)
296f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
297f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
298f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public boolean remove(Object o) {
299ab4f6a5743de6a9fbb09da9d6a00678bbc2cd3d1Federico Tomassetti        if (o instanceof Node) {
3004296abb695b767f7471dd255d0679516183b062aDanny van Bruggen            return remove((Node) o);
301ab4f6a5743de6a9fbb09da9d6a00678bbc2cd3d1Federico Tomassetti        } else {
302ab4f6a5743de6a9fbb09da9d6a00678bbc2cd3d1Federico Tomassetti            return false;
303ab4f6a5743de6a9fbb09da9d6a00678bbc2cd3d1Federico Tomassetti        }
304f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
305f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
306f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
307f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#containsAll(java.util.Collection)
308f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
309f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
310f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public boolean containsAll(Collection<?> c) {
311f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.containsAll(c);
312f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
313f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
314f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
315f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#addAll(java.util.Collection)
316f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
317f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
318f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public boolean addAll(Collection<? extends N> c) {
3199dfe6cb2a1115f749a6a9adca05297d6b24eb046Danny van Bruggen        c.forEach(this::add);
3203e8757e510df2bbdb1ef8bedf92538b17a5e36c6Federico Tomassetti        return !c.isEmpty();
321f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
322f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
323f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
324f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#addAll(int, java.util.Collection)
325f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
326f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
327f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public boolean addAll(int index, Collection<? extends N> c) {
328150ecb8efecf1bbe22f23e6e2869ef4f59fe3523Federico Tomassetti        for (N e : c) {
329150ecb8efecf1bbe22f23e6e2869ef4f59fe3523Federico Tomassetti            add(index++, e);
3303e8757e510df2bbdb1ef8bedf92538b17a5e36c6Federico Tomassetti        }
331150ecb8efecf1bbe22f23e6e2869ef4f59fe3523Federico Tomassetti        return !c.isEmpty();
332f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
333f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
334f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
335f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#removeAll(java.util.Collection)
336f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
337f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
338f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public boolean removeAll(Collection<?> c) {
339ab4f6a5743de6a9fbb09da9d6a00678bbc2cd3d1Federico Tomassetti        boolean changed = false;
340ab4f6a5743de6a9fbb09da9d6a00678bbc2cd3d1Federico Tomassetti        for (Object e : c) {
341ab4f6a5743de6a9fbb09da9d6a00678bbc2cd3d1Federico Tomassetti            changed = remove(e) || changed;
342f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        }
343ab4f6a5743de6a9fbb09da9d6a00678bbc2cd3d1Federico Tomassetti        return changed;
344f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
345f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
346f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
347f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#retainAll(java.util.Collection)
348f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
349f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
350f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public boolean retainAll(Collection<?> c) {
351cbaf4495c17eb3383e8d2b40db9a4fe92221d118Federico Tomassetti        boolean changed = false;
352cbaf4495c17eb3383e8d2b40db9a4fe92221d118Federico Tomassetti        for (Object e : this.stream().filter(it -> !c.contains(it)).toArray()) {
353cbaf4495c17eb3383e8d2b40db9a4fe92221d118Federico Tomassetti            if (!c.contains(e)) {
354cbaf4495c17eb3383e8d2b40db9a4fe92221d118Federico Tomassetti                changed = remove(e) || changed;
355cbaf4495c17eb3383e8d2b40db9a4fe92221d118Federico Tomassetti            }
356cbaf4495c17eb3383e8d2b40db9a4fe92221d118Federico Tomassetti        }
357cbaf4495c17eb3383e8d2b40db9a4fe92221d118Federico Tomassetti        return changed;
358f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
359f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
360f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
361f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#replaceAll(java.util.function.UnaryOperator)
362f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
363f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
364f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public void replaceAll(UnaryOperator<N> operator) {
3654296abb695b767f7471dd255d0679516183b062aDanny van Bruggen        for (int i = 0; i < this.size(); i++) {
36634ee4b944cf1534361d6d9ca7ba3f9876df5ddb4Federico Tomassetti            set(i, operator.apply(this.get(i)));
36734ee4b944cf1534361d6d9ca7ba3f9876df5ddb4Federico Tomassetti        }
368f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
369f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
370f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
371f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.Collection#removeIf(java.util.function.Predicate)
372f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
373f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
374f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public boolean removeIf(Predicate<? super N> filter) {
37555d475bac6deff387e608ac7f200227a23488ea7Federico Tomassetti        boolean changed = false;
3764296abb695b767f7471dd255d0679516183b062aDanny van Bruggen        for (Object e : this.stream().filter(filter).toArray()) {
37755d475bac6deff387e608ac7f200227a23488ea7Federico Tomassetti            changed = remove(e) || changed;
37855d475bac6deff387e608ac7f200227a23488ea7Federico Tomassetti        }
37955d475bac6deff387e608ac7f200227a23488ea7Federico Tomassetti        return changed;
380f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
381f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
382f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
383f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#clear()
384f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
385f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
386f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public void clear() {
3874a25ff22c5db52fe1f21f8939e4a47a73ff2f61bFederico Tomassetti        while (!isEmpty()) {
3884a25ff22c5db52fe1f21f8939e4a47a73ff2f61bFederico Tomassetti            remove(0);
3894a25ff22c5db52fe1f21f8939e4a47a73ff2f61bFederico Tomassetti        }
390f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
391f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
392f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
393f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#equals(java.lang.Object)
394f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
395f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
396f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public boolean equals(Object o) {
397f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.equals(o);
398f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
399f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
400f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
401f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#hashCode()
402f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
403f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
404f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public int hashCode() {
405f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.hashCode();
406f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
407f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
408f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
409f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#indexOf(java.lang.Object)
410f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
411f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
412f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public int indexOf(Object o) {
413f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.indexOf(o);
414f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
415f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
416f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
417f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#lastIndexOf(java.lang.Object)
418f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
419f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
420f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public int lastIndexOf(Object o) {
421f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.lastIndexOf(o);
422f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
423f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
424f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
425f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#listIterator()
426f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
427f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
428f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public ListIterator<N> listIterator() {
429f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.listIterator();
430f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
431f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
432f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
433f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#listIterator(int)
434f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
435f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
436f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public ListIterator<N> listIterator(int index) {
437f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.listIterator(index);
438f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
439f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
440f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
441f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.Collection#parallelStream()
442f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
443f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
444f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public Stream<N> parallelStream() {
445f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.parallelStream();
446f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
447f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
448f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
449f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#subList(int, int)
450f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
451f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
452f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public List<N> subList(int fromIndex, int toIndex) {
453f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.subList(fromIndex, toIndex);
454f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
455f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
456f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    /**
457f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     * @see java.util.List#spliterator()
458f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien     */
459f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    @Override
460f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    public Spliterator<N> spliterator() {
461f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien        return innerList.spliterator();
462c77e046d2a645bf42f9450bd293e0ba69300a309Federico Tomassetti    }
463263cf50ac27714b8e120565f45a1fac661df18b5Federico Tomassetti
4646d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti    private void notifyElementAdded(int index, Node nodeAddedOrRemoved) {
46517c60f99a730acb68276303e7c6fcdf0a376258cFederico Tomassetti        this.observers.forEach(o -> o.listChange(this, AstObserver.ListChangeType.ADDITION, index, nodeAddedOrRemoved));
4666d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti    }
4676d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti
4686d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti    private void notifyElementRemoved(int index, Node nodeAddedOrRemoved) {
46917c60f99a730acb68276303e7c6fcdf0a376258cFederico Tomassetti        this.observers.forEach(o -> o.listChange(this, AstObserver.ListChangeType.REMOVAL, index, nodeAddedOrRemoved));
4706d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti    }
4716d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti
4720d8f8e5cc0e48d0cc27cf070155ab318fe160a00Federico Tomassetti    private void notifyElementReplaced(int index, Node nodeAddedOrRemoved) {
4730d8f8e5cc0e48d0cc27cf070155ab318fe160a00Federico Tomassetti        this.observers.forEach(o -> o.listReplacement(this, index, this.get(index), nodeAddedOrRemoved));
4740d8f8e5cc0e48d0cc27cf070155ab318fe160a00Federico Tomassetti    }
4750d8f8e5cc0e48d0cc27cf070155ab318fe160a00Federico Tomassetti
4766d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti    @Override
477263cf50ac27714b8e120565f45a1fac661df18b5Federico Tomassetti    public void unregister(AstObserver observer) {
4786d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti        this.observers.remove(observer);
4796d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti    }
4806d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti
4816d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti    @Override
482263cf50ac27714b8e120565f45a1fac661df18b5Federico Tomassetti    public void register(AstObserver observer) {
4836d41743d2b5dcd565b401a27f62526ec7a7b54d4Federico Tomassetti        this.observers.add(observer);
484263cf50ac27714b8e120565f45a1fac661df18b5Federico Tomassetti    }
485263cf50ac27714b8e120565f45a1fac661df18b5Federico Tomassetti
486263cf50ac27714b8e120565f45a1fac661df18b5Federico Tomassetti    @Override
487263cf50ac27714b8e120565f45a1fac661df18b5Federico Tomassetti    public boolean isRegistered(AstObserver observer) {
488263cf50ac27714b8e120565f45a1fac661df18b5Federico Tomassetti        return this.observers.contains(observer);
489f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien    }
490f1cce0ac20c5af34085d891bee6d9ff9012d36c7Cruz Maximilien
491f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen    /**
492f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen     * Replaces the first node that is equal to "old" with "replacement".
493f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen     *
494f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen     * @return true if a replacement has happened.
495f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen     */
496f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen    public boolean replace(N old, N replacement) {
497f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen        int i = indexOf(old);
498f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen        if (i == -1) {
499f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen            return false;
500f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen        }
501f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen        set(i, replacement);
502f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen        return true;
503f64e8f570cb375692d112e03d095040e88d109abDanny van Bruggen    }
50426ddbc38a65a4a8350afcb569923d7d66b7e6ee2Danny van Bruggen
50526ddbc38a65a4a8350afcb569923d7d66b7e6ee2Danny van Bruggen    /**
50626ddbc38a65a4a8350afcb569923d7d66b7e6ee2Danny van Bruggen     * @return the opposite of isEmpty()
50726ddbc38a65a4a8350afcb569923d7d66b7e6ee2Danny van Bruggen     */
50826ddbc38a65a4a8350afcb569923d7d66b7e6ee2Danny van Bruggen    public boolean isNonEmpty() {
50926ddbc38a65a4a8350afcb569923d7d66b7e6ee2Danny van Bruggen        return !isEmpty();
51026ddbc38a65a4a8350afcb569923d7d66b7e6ee2Danny van Bruggen    }
5117cd83c2e73deb47d79e71cc6afc3eb4b613302d1Danny van Bruggen
5127cd83c2e73deb47d79e71cc6afc3eb4b613302d1Danny van Bruggen    public void ifNonEmpty(Consumer<? super NodeList<N>> consumer) {
5137cd83c2e73deb47d79e71cc6afc3eb4b613302d1Danny van Bruggen        if (isNonEmpty())
5147cd83c2e73deb47d79e71cc6afc3eb4b613302d1Danny van Bruggen            consumer.accept(this);
5157cd83c2e73deb47d79e71cc6afc3eb4b613302d1Danny van Bruggen    }
516c9f2a4fe27453e09a268730cd0ab76a42016475fDanny van Bruggen
517c9f2a4fe27453e09a268730cd0ab76a42016475fDanny van Bruggen    public static <T extends Node> Collector<T, NodeList<T>, NodeList<T>> toNodeList() {
518c9f2a4fe27453e09a268730cd0ab76a42016475fDanny van Bruggen        return Collector.of(NodeList::new, NodeList::add, (left, right) -> {
519c9f2a4fe27453e09a268730cd0ab76a42016475fDanny van Bruggen            left.addAll(right);
520c9f2a4fe27453e09a268730cd0ab76a42016475fDanny van Bruggen            return left;
521c9f2a4fe27453e09a268730cd0ab76a42016475fDanny van Bruggen        });
522c9f2a4fe27453e09a268730cd0ab76a42016475fDanny van Bruggen    }
5234ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen
5244ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen    private void setAsParentNodeOf(List<? extends Node> childNodes) {
5254ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen        if (childNodes != null) {
5264ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen            for (HasParentNode current : childNodes) {
5274ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen                current.setParentNode(getParentNodeForChildren());
5284ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen            }
5294ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen        }
5304ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen    }
5314ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen
5324ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen    private void setAsParentNodeOf(Node childNode) {
5334ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen        if (childNode != null) {
5344ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen            childNode.setParentNode(getParentNodeForChildren());
5354ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen        }
5364ea99f582d159e166eef3c6cc48a33bc85f2b22fDanny van Bruggen    }
5373b31ef89fd3f2963c2bf53655f42ed459376e879Danny van Bruggen
5383b31ef89fd3f2963c2bf53655f42ed459376e879Danny van Bruggen    @Override
5393b31ef89fd3f2963c2bf53655f42ed459376e879Danny van Bruggen    public String toString() {
540716c3b490fe90c09b9ca66d66569eb58f52e8b48Danny van Bruggen        return innerList.stream().map(Node::toString).collect(Collectors.joining(", ", "[", "]"));
5413b31ef89fd3f2963c2bf53655f42ed459376e879Danny van Bruggen    }
542515a9392928c14a60dc9dfa42a98198a4d877534Danny van Bruggen}
543