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             next_ = parent_.getFirstChild();
104             nextIndex_ = 0;
105             for (int i = 0; i < index; i++) {
106                 next();
107             }
108         }
109 
110         /**
111          * {@inheritDoc}
112          */
113         @Override
114         public boolean hasNext() {
115             return next_ != null;
116         }
117 
118         /**
119          * {@inheritDoc}
120          */
121         @Override
122         public DomNode next() {
123             if (!hasNext()) {
124                 throw new NoSuchElementException();
125             }
126             prev_ = next_;
127             next_ = next_.getNextSibling();
128             nextIndex_++;
129             return prev_;
130         }
131 
132         /**
133          * {@inheritDoc}
134          */
135         @Override
136         public boolean hasPrevious() {
137             return prev_ != null;
138         }
139 
140         @Override
141         public DomNode previous() {
142             if (!hasPrevious()) {
143                 throw new NoSuchElementException();
144             }
145             next_ = prev_;
146             prev_ = prev_.getPreviousSibling();
147             nextIndex_--;
148             return next_;
149         }
150 
151         @Override
152         public int nextIndex() {
153             return nextIndex_;
154         }
155 
156         @Override
157         public int previousIndex() {
158             return nextIndex_ - 1;
159         }
160 
161         @Override
162         public void add(final DomNode e) {
163             throw new UnsupportedOperationException();
164         }
165 
166         @Override
167         public void remove() {
168             throw new UnsupportedOperationException();
169         }
170 
171         @Override
172         public void set(final DomNode e) {
173             throw new UnsupportedOperationException();
174         }
175     }
176 }