View Javadoc
1   /*
2    * Copyright (c) 2002-2025 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 <a href="mailto:tom.anderson@univ.oxon.org">Tom Anderson</a>
27   */
28  class SiblingDomNodeList extends AbstractSequentialList<DomNode> implements DomNodeList<DomNode> {
29  
30      private final DomNode parent_;
31  
32      SiblingDomNodeList(final DomNode parent) {
33          super();
34          parent_ = parent;
35      }
36  
37      /**
38       * {@inheritDoc}
39       */
40      @Override
41      public int getLength() {
42          int length = 0;
43          for (DomNode node = parent_.getFirstChild(); node != null; node = node.getNextSibling()) {
44              length++;
45          }
46          return length;
47      }
48  
49      /**
50       * {@inheritDoc}
51       */
52      @Override
53      public int size() {
54          return getLength();
55      }
56  
57      /**
58       * {@inheritDoc}
59       */
60      @Override
61      public Node item(final int index) {
62          return get(index);
63      }
64  
65      /**
66       * {@inheritDoc}
67       */
68      @Override
69      public DomNode get(final int index) {
70          int i = 0;
71          for (DomNode node = parent_.getFirstChild(); node != null; node = node.getNextSibling()) {
72              if (i == index) {
73                  return node;
74              }
75              i++;
76          }
77          return null;
78      }
79  
80      /**
81       * {@inheritDoc}
82       */
83      @Override
84      public ListIterator<DomNode> listIterator(final int index) {
85          return new SiblingListIterator(index);
86      }
87  
88      /**
89       * {@inheritDoc}
90       */
91      @Override
92      public String toString() {
93          return "SiblingDomNodeList[" + parent_ + "]";
94      }
95  
96      private class SiblingListIterator implements ListIterator<DomNode> {
97          private DomNode prev_;
98          private DomNode next_;
99          private int nextIndex_;
100 
101         SiblingListIterator(final int index) {
102             next_ = parent_.getFirstChild();
103             nextIndex_ = 0;
104             for (int i = 0; i < index; i++) {
105                 next();
106             }
107         }
108 
109         /**
110          * {@inheritDoc}
111          */
112         @Override
113         public boolean hasNext() {
114             return next_ != null;
115         }
116 
117         /**
118          * {@inheritDoc}
119          */
120         @Override
121         public DomNode next() {
122             if (!hasNext()) {
123                 throw new NoSuchElementException();
124             }
125             prev_ = next_;
126             next_ = next_.getNextSibling();
127             nextIndex_++;
128             return prev_;
129         }
130 
131         /**
132          * {@inheritDoc}
133          */
134         @Override
135         public boolean hasPrevious() {
136             return prev_ != null;
137         }
138 
139         @Override
140         public DomNode previous() {
141             if (!hasPrevious()) {
142                 throw new NoSuchElementException();
143             }
144             next_ = prev_;
145             prev_ = prev_.getPreviousSibling();
146             nextIndex_--;
147             return next_;
148         }
149 
150         @Override
151         public int nextIndex() {
152             return nextIndex_;
153         }
154 
155         @Override
156         public int previousIndex() {
157             return nextIndex_ - 1;
158         }
159 
160         @Override
161         public void add(final DomNode e) {
162             throw new UnsupportedOperationException();
163         }
164 
165         @Override
166         public void remove() {
167             throw new UnsupportedOperationException();
168         }
169 
170         @Override
171         public void set(final DomNode e) {
172             throw new UnsupportedOperationException();
173         }
174     }
175 }