View Javadoc
1   /*
2    * Copyright (c) 2002-2026 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.html;
16  
17  import java.util.AbstractSequentialList;
18  import java.util.ListIterator;
19  import java.util.NoSuchElementException;
20  
21  import org.w3c.dom.Node;
22  
23  /**
24   * An implementation of DomNodeList that is much less expensive for iteration.
25   *
26   * @author Tom Anderson
27   * @author Ronald Brill
28   */
29  class SiblingDomNodeList extends AbstractSequentialList<DomNode> implements DomNodeList<DomNode> {
30  
31      private final DomNode parent_;
32  
33      SiblingDomNodeList(final DomNode parent) {
34          super();
35          parent_ = parent;
36      }
37  
38      /**
39       * {@inheritDoc}
40       */
41      @Override
42      public int getLength() {
43          int length = 0;
44          for (DomNode node = parent_.getFirstChild(); node != null; node = node.getNextSibling()) {
45              length++;
46          }
47          return length;
48      }
49  
50      /**
51       * {@inheritDoc}
52       */
53      @Override
54      public int size() {
55          return getLength();
56      }
57  
58      /**
59       * {@inheritDoc}
60       */
61      @Override
62      public Node item(final int index) {
63          return get(index);
64      }
65  
66      /**
67       * {@inheritDoc}
68       */
69      @Override
70      public DomNode get(final int index) {
71          int i = 0;
72          for (DomNode node = parent_.getFirstChild(); node != null; node = node.getNextSibling()) {
73              if (i == index) {
74                  return node;
75              }
76              i++;
77          }
78          return null;
79      }
80  
81      /**
82       * {@inheritDoc}
83       */
84      @Override
85      public ListIterator<DomNode> listIterator(final int index) {
86          return new SiblingListIterator(index);
87      }
88  
89      /**
90       * {@inheritDoc}
91       */
92      @Override
93      public String toString() {
94          return "SiblingDomNodeList[" + parent_ + "]";
95      }
96  
97      private class SiblingListIterator implements ListIterator<DomNode> {
98          private DomNode prev_;
99          private DomNode next_;
100         private int nextIndex_;
101 
102         SiblingListIterator(final int index) {
103             if (index < 0) {
104                 throw new IndexOutOfBoundsException("index: " + index);
105             }
106 
107             next_ = parent_.getFirstChild();
108             nextIndex_ = 0;
109             for (int i = 0; i < index; i++) {
110                 if (next_ == null) {
111                     throw new IndexOutOfBoundsException("index: " + index + ", size: " + nextIndex_);
112                 }
113                 prev_ = next_;
114                 next_ = next_.getNextSibling();
115                 nextIndex_++;
116             }
117         }
118 
119         /**
120          * {@inheritDoc}
121          */
122         @Override
123         public boolean hasNext() {
124             return next_ != null;
125         }
126 
127         /**
128          * {@inheritDoc}
129          */
130         @Override
131         public DomNode next() {
132             if (!hasNext()) {
133                 throw new NoSuchElementException();
134             }
135             prev_ = next_;
136             next_ = next_.getNextSibling();
137             nextIndex_++;
138             return prev_;
139         }
140 
141         /**
142          * {@inheritDoc}
143          */
144         @Override
145         public boolean hasPrevious() {
146             return prev_ != null;
147         }
148 
149         @Override
150         public DomNode previous() {
151             if (!hasPrevious()) {
152                 throw new NoSuchElementException();
153             }
154             next_ = prev_;
155             prev_ = prev_.getPreviousSibling();
156             nextIndex_--;
157             return next_;
158         }
159 
160         @Override
161         public int nextIndex() {
162             return nextIndex_;
163         }
164 
165         @Override
166         public int previousIndex() {
167             return nextIndex_ - 1;
168         }
169 
170         @Override
171         public void add(final DomNode e) {
172             throw new UnsupportedOperationException();
173         }
174 
175         @Override
176         public void remove() {
177             throw new UnsupportedOperationException();
178         }
179 
180         @Override
181         public void set(final DomNode e) {
182             throw new UnsupportedOperationException();
183         }
184     }
185 }