source: trunk/gli/src/org/greenstone/gatherer/cdm/DOMProxyListModel.java@ 8607

Last change on this file since 8607 was 8380, checked in by kjdon, 20 years ago

I seemed to get into a situation where children was null. It only appears to be assigned when you call getSize, and is never changed after that, so I just assigned it in the constructor, and when the root element is changed. hopefully its still ok

  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29import java.util.*;
30import javax.swing.*;
31import org.w3c.dom.*;
32
33/** This class provides ListModel like access to a list of nodes within a DOM model.
34 * @author John Thompson, Greenstone Digital Library, University of Waikato
35 * @version 2.3d
36 */
37public class DOMProxyListModel
38 extends AbstractListModel {
39 protected Element root;
40 private DOMProxyListEntry class_type;
41 private HashMap cache = new HashMap();
42 private NodeList children = null;
43 private String tag_name;
44
45 /** Constructor.
46 * @param root the Element at the root of the subtree to be searched for appropriate child elements
47 * @param tag_name the name of appropriate elements as a String
48 * @param class_type the type of object to wrap the elements returned in, as a DOMProxyListEntry
49 */
50 public DOMProxyListModel(Element root, String tag_name, DOMProxyListEntry class_type) {
51 this.class_type = class_type;
52 this.root = root;
53 this.tag_name = tag_name;
54 this.children = this.root.getElementsByTagName(this.tag_name);
55 }
56
57 /** Used to add an element into the underlying dom, and fire the appropriate repaint events. This version always adds the new element at the very head of the DOM. */
58 public synchronized void add(DOMProxyListEntry entry) {
59 Element element = entry.getElement();
60 if(root.hasChildNodes()) {
61 Node sibling = root.getFirstChild();
62 root.insertBefore(element, sibling);
63 sibling = null;
64 }
65 else {
66 root.appendChild(element);
67 }
68 element = null;
69 // Regardless fire update event
70 cache.clear();
71 fireIntervalAdded(this, 0, 0);
72 }
73
74 /** Used to add an element into the underlying dom, and fire the appropriate repaint events.
75 * @param index the index where the element should be inserted (relative of the other elements in this proxy list)
76 * @param entry the <strong>DOMProxyListEntry</strong> to be inserted
77 */
78 public synchronized void add(int index, DOMProxyListEntry entry) {
79 ///atherer.println("Add entry at " + index + " where size = " + getSize());
80 Element element = entry.getElement();
81 // retrieve the node where we want to insert
82 if(index < children.getLength()) {
83 Node sibling = children.item(index);
84 // Find the parent node
85 Node parent_node = sibling.getParentNode();
86 parent_node.insertBefore(element, sibling);
87 sibling = null;
88 }
89 // If the index is too large, we are adding to the end of our list of entries. However you have to remember that this list is only a viewport on the entire DOM so there might be entries following this group that we actually want to insert before (not append at the very end!)
90 else {
91 // Retrieve the currently last entry
92 index = children.getLength() - 1;
93 Node sibling = null;
94 Node parent_node = null;
95 if(index >= 0) {
96 sibling = children.item(index);
97 parent_node = sibling.getParentNode();
98 sibling = sibling.getNextSibling();
99 }
100 if(sibling != null && parent_node != null) {
101 parent_node.insertBefore(element, sibling);
102 }
103 // Add to the root node
104 else {
105 index = 0;
106 root.appendChild(element);
107 }
108 }
109 // Regardless fire update event
110 cache.clear();
111 fireIntervalAdded(this, index, index);
112 }
113
114 /** Used to add an element into the underlying dom, and fire the appropriate repaint events. This version inserts the new entry immediately -after- the given entry in the DOM.
115 * @param entry the DOMProxyListEntry to be inserted
116 * @param proceeding_entry the DOMProxyListEntry immediately before where we want the new entry
117 */
118 public synchronized void addAfter(DOMProxyListEntry entry, DOMProxyListEntry proceeding_entry) {
119 Element element = entry.getElement();
120 Element proceeding_sibling = proceeding_entry.getElement();
121 Node parent_node = proceeding_sibling.getParentNode();
122 Node following_sibling = proceeding_sibling.getNextSibling();
123 if(following_sibling != null) {
124 parent_node.insertBefore(element, following_sibling);
125 }
126 else {
127 parent_node.appendChild(element);
128 }
129 // Regardless fire update event
130 cache.clear();
131 int index = indexOf(proceeding_entry) + 1;
132 fireIntervalAdded(this, index, index);
133 }
134
135 /** Used to add an element into the underlying dom, and fire the appropriate repaint events. This version inserts the new entry immediately -before- the given entry in the DOM.
136 * @param entry the DOMProxyListEntry to be inserted
137 * @param following_entry the DOMProxyListEntry immediately after where we want the new entry
138 */
139 public synchronized void addBefore(DOMProxyListEntry entry, DOMProxyListEntry following_entry) {
140 Element element = entry.getElement();
141 Element following_sibling = following_entry.getElement();
142 Node parent_node = following_sibling.getParentNode();
143 parent_node.insertBefore(element, following_sibling);
144 // Regardless fire update event
145 cache.clear();
146 int index = indexOf(entry);
147 fireIntervalAdded(this, index, index);
148 }
149
150 public synchronized void add(Node parent, DOMProxyListEntry entry, Node sibling) {
151 Element child = entry.getElement();
152 if(sibling != null) {
153 parent.insertBefore(child, sibling);
154 }
155 else {
156 parent.appendChild(child);
157 }
158 cache.clear();
159 int index = indexOf(entry);
160 fireIntervalAdded(this, index, index);
161 }
162
163 /** Used to add an element into the underlying dom, and fire the appropriate repaint events. This version always adds the new element at the end of the children. */
164 public synchronized void append(DOMProxyListEntry entry) {
165 Element element = entry.getElement();
166 root.appendChild(element);
167 element = null;
168 // Regardless fire update event
169 cache.clear();
170 fireIntervalAdded(this, 0, 0);
171 }
172
173 public synchronized ArrayList children() {
174 ArrayList child_list = new ArrayList();
175 int child_count = children.getLength();
176 for(int i = 0; i < child_count; i++) {
177 child_list.add(getElementAt(i));
178 }
179 return child_list;
180 }
181
182 public synchronized boolean contains(Object entry) {
183 boolean found = false;
184 int size = getSize();
185 for(int i = 0; !found && i < size; i++) {
186 DOMProxyListEntry sibling = (DOMProxyListEntry) getElementAt(i);
187 if(sibling.equals(entry)) {
188 found = true;
189 }
190 }
191 return found;
192 }
193
194 public synchronized Object getElementAt(int index) {
195 Object object = cache.get(new Integer(index));
196 if(object == null) {
197 // Retrieve the required element
198 Element element = (Element) children.item(index);
199 // Now wrap it in the object of the users choice
200 object = class_type.create(element);
201 cache.put(new Integer(index), object);
202 }
203 return object;
204 }
205
206 public synchronized int indexOf(DOMProxyListEntry entry) {
207 Element element = entry.getElement();
208 int children_length = children.getLength();
209 for(int i = 0; i < children_length; i++) {
210 Node node = children.item(i);
211 if(element == node) {
212 return i;
213 }
214 }
215 return -1;
216 }
217
218 public synchronized int getSize() {
219 if(children == null) {
220 children = root.getElementsByTagName(tag_name);
221 }
222 return children.getLength();
223 }
224
225 public synchronized void refresh() {
226 fireContentsChanged(this, 0, getSize());
227 }
228
229 public synchronized void refresh(DOMProxyListEntry entry) {
230 int index = indexOf(entry);
231 fireContentsChanged(this, index, index);
232 }
233
234 public synchronized void remove(DOMProxyListEntry entry) {
235 remove(indexOf(entry));
236 }
237
238 public synchronized void remove(int index) {
239 // Retrieve the required element
240 Node node = children.item(index);
241 // Find its parent
242 Node parent_node = node.getParentNode();
243 // Now remove it
244 parent_node.removeChild(node);
245 // Refresh model
246 cache.clear();
247 fireIntervalRemoved(this, index, index);
248 }
249
250 /** Changes the 'root' element that this list sources its information from.
251 * @param root the new root Element
252 */
253 public synchronized void setRoot(Element root) {
254 this.children = null;
255 cache.clear();
256 this.root = root;
257 this.children = this.root.getElementsByTagName(this.tag_name);
258 }
259}
Note: See TracBrowser for help on using the repository browser.