1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.html;
16
17 import java.io.Serializable;
18 import java.lang.ref.WeakReference;
19 import java.util.AbstractList;
20 import java.util.Collections;
21 import java.util.List;
22
23 import org.w3c.dom.Node;
24
25
26
27
28
29
30
31
32
33
34 public abstract class AbstractDomNodeList<E extends DomNode> extends AbstractList<E>
35 implements DomNodeList<E>, Serializable {
36
37
38 private final DomNode node_;
39
40
41 private List<E> cachedElements_;
42
43
44
45
46
47
48 public AbstractDomNodeList(final DomNode node) {
49 super();
50 node_ = node;
51
52 if (node == null) {
53 cachedElements_ = Collections.EMPTY_LIST;
54 return;
55 }
56
57 final DomHtmlAttributeChangeListenerImpl listener = new DomHtmlAttributeChangeListenerImpl(this);
58 node_.addDomChangeListener(listener);
59 }
60
61
62
63
64
65 protected DomNode getDomNode() {
66 return node_;
67 }
68
69
70
71
72
73 protected abstract List<E> provideElements();
74
75
76
77
78
79 private List<E> getNodes() {
80
81
82
83
84
85
86
87 List<E> shortLivedCache = cachedElements_;
88 if (cachedElements_ == null) {
89 shortLivedCache = provideElements();
90 cachedElements_ = shortLivedCache;
91 }
92 return shortLivedCache;
93 }
94
95
96
97
98 @Override
99 public int size() {
100 return getLength();
101 }
102
103
104
105
106 @Override
107 public int getLength() {
108 return getNodes().size();
109 }
110
111
112
113
114 @Override
115 public Node item(final int index) {
116 return getNodes().get(index);
117 }
118
119
120
121
122 @Override
123 public E get(final int index) {
124 return getNodes().get(index);
125 }
126
127
128
129
130 private static final class DomHtmlAttributeChangeListenerImpl implements DomChangeListener {
131
132 private final transient WeakReference<AbstractDomNodeList<?>> nodeList_;
133
134 DomHtmlAttributeChangeListenerImpl(final AbstractDomNodeList<?> nodeList) {
135 super();
136
137 nodeList_ = new WeakReference<>(nodeList);
138 }
139
140
141
142
143 @Override
144 public void nodeAdded(final DomChangeEvent event) {
145 clearCache();
146 }
147
148
149
150
151 @Override
152 public void nodeDeleted(final DomChangeEvent event) {
153 clearCache();
154 }
155
156 private void clearCache() {
157 if (nodeList_ != null) {
158 final AbstractDomNodeList<?> nodes = nodeList_.get();
159 if (nodes != null && nodes.node_ != null) {
160 nodes.cachedElements_ = null;
161 }
162 }
163 }
164 }
165
166 }