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

Last change on this file since 18608 was 18608, checked in by kjdon, 15 years ago

return null if we are asking for an index that does not exist, in getElementAt. HOpe this doesn't stuff up anything else

  • Property svn:keywords set to Author Date Id Revision
File size: 11.6 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.greenstone.gatherer.DebugStream;
32import org.greenstone.gatherer.util.StaticStrings;
33import org.greenstone.gatherer.util.XMLTools;
34import org.w3c.dom.*;
35
36/** This class provides ListModel like access to a list of nodes within a DOM model.
37 * @author John Thompson, Greenstone Digital Library, University of Waikato
38 * @version 2.3d
39 */
40public class DOMProxyListModel
41extends AbstractListModel {
42 protected Element root;
43 private DOMProxyListEntry class_type;
44 private HashMap cache = new HashMap ();
45 private NodeList children = null;
46 private String tag_name;
47
48 /** Constructor.
49 * @param root the Element at the root of the subtree to be searched for appropriate child elements
50 * @param tag_name the name of appropriate elements as a String
51 * @param class_type the type of object to wrap the elements returned in, as a DOMProxyListEntry
52 */
53 public DOMProxyListModel (Element root, String tag_name, DOMProxyListEntry class_type) {
54 this.class_type = class_type;
55 this.root = root;
56 this.tag_name = tag_name;
57 this.children = this.root.getElementsByTagName (this.tag_name);
58 }
59
60 /** 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. */
61 public synchronized void add (DOMProxyListEntry entry) {
62 Element element = entry.getElement ();
63 if(root.hasChildNodes ()) {
64 Node sibling = root.getFirstChild ();
65 root.insertBefore (element, sibling);
66 sibling = null;
67 }
68 else {
69 root.appendChild (element);
70 }
71 element = null;
72 // Regardless fire update event
73 cache.clear ();
74 fireIntervalAdded (this, 0, 0);
75 }
76
77 /** Used to add an element into the underlying dom, and fire the appropriate repaint events.
78 * @param index the index where the element should be inserted (relative of the other elements in this proxy list)
79 * @param entry the <strong>DOMProxyListEntry</strong> to be inserted
80 */
81 public synchronized void add (int index, DOMProxyListEntry entry) {
82 ///atherer.println("Add entry at " + index + " where size = " + getSize());
83 Element element = entry.getElement ();
84 // retrieve the node where we want to insert
85 if(index < children.getLength ()) {
86 Node sibling = children.item (index);
87 // Find the parent node
88 Node parent_node = sibling.getParentNode ();
89 parent_node.insertBefore (element, sibling);
90 sibling = null;
91 }
92 // 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!)
93 else {
94 // Retrieve the currently last entry
95 index = children.getLength () - 1;
96 Node sibling = null;
97 Node parent_node = null;
98 if(index >= 0) {
99 sibling = children.item (index);
100 parent_node = sibling.getParentNode ();
101 sibling = sibling.getNextSibling ();
102 }
103 if(sibling != null && parent_node != null) {
104 parent_node.insertBefore (element, sibling);
105 }
106 // Add to the root node
107 else {
108 index = 0;
109 root.appendChild (element);
110 }
111 }
112 // Regardless fire update event
113 cache.clear ();
114 fireIntervalAdded (this, index, index);
115 }
116
117 /** 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.
118 * @param entry the DOMProxyListEntry to be inserted
119 * @param preceeding_entry the DOMProxyListEntry immediately before where we want the new entry
120 */
121 public synchronized void addAfter (DOMProxyListEntry entry, DOMProxyListEntry preceeding_entry) {
122 Element element = entry.getElement ();
123 Element preceeding_sibling = preceeding_entry.getElement ();
124 Node parent_node = preceeding_sibling.getParentNode ();
125 Node following_sibling = preceeding_sibling.getNextSibling ();
126 if(following_sibling != null) {
127 parent_node.insertBefore (element, following_sibling);
128 }
129 else {
130 parent_node.appendChild (element);
131 }
132 // Regardless fire update event
133 cache.clear ();
134 int index = indexOf (entry);
135 fireIntervalAdded (this, index, index);
136 }
137
138 /** 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.
139 * @param entry the DOMProxyListEntry to be inserted
140 * @param following_entry the DOMProxyListEntry immediately after where we want the new entry
141 */
142 public synchronized void addBefore (DOMProxyListEntry entry, DOMProxyListEntry following_entry) {
143 Element element = entry.getElement ();
144 Element following_sibling = following_entry.getElement ();
145 Node parent_node = following_sibling.getParentNode ();
146 parent_node.insertBefore (element, following_sibling);
147 // Regardless fire update event
148 cache.clear ();
149 int index = indexOf (entry);
150 fireIntervalAdded (this, index, index);
151 }
152
153 public synchronized void add (Node parent, DOMProxyListEntry entry, Node sibling) {
154 Element child = entry.getElement ();
155 if(sibling != null) {
156 parent.insertBefore (child, sibling);
157 }
158 else {
159 parent.appendChild (child);
160 }
161 cache.clear ();
162 int index = indexOf (entry);
163
164
165 fireIntervalAdded (this, index, index);
166 }
167
168 /** 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. */
169 public synchronized void append (DOMProxyListEntry entry) {
170 Element element = entry.getElement ();
171 root.appendChild (element);
172 element = null;
173 // Regardless fire update event
174 cache.clear ();
175 fireIntervalAdded (this, 0, 0);
176 }
177
178 public synchronized ArrayList children () {
179 ArrayList child_list = new ArrayList ();
180 int child_count = children.getLength ();
181 for(int i = 0; i < child_count; i++) {
182 child_list.add (getElementAt (i));
183 }
184 return child_list;
185 }
186
187 public synchronized boolean contains (Object entry) {
188 boolean found = false;
189 int size = getSize ();
190
191 for(int i = 0; !found && i < size; i++) {
192 DOMProxyListEntry sibling = (DOMProxyListEntry) getElementAt (i);
193 if(sibling.equals (entry)) {
194
195 found = true;
196 }
197 }
198 return found;
199 }
200
201 public synchronized Object getElementAt (int index) {
202 /** There are times when the length of the 'cache' is not as same as the length of the 'children', etc. not up to date.
203 eg, when a classifier has been deleted. So we rather not have this efficiency for Format4gs3.java.*/
204 if (class_type instanceof Format4gs3) {
205 Element element = (Element) children.item (index);
206 // Now wrap it in the object of the users choice
207 Object object = class_type.create (element);
208 return object;
209 }
210
211 Object object = cache.get (new Integer (index));
212 if (object != null) {
213 return object;
214 }
215
216 // Retrieve the required element
217 Element element = (Element) children.item (index);
218 if (element == null) {
219 return null;
220 }
221 DebugStream.println ("Element at index " + index + " not in cache: " + element);
222
223 // Now wrap it in the object of the users choice
224 object = class_type.create (element);
225 cache.put (new Integer (index), object);
226 return object;
227 }
228
229 public synchronized int indexOf (DOMProxyListEntry entry) {
230 Element element = entry.getElement ();
231 int children_length = children.getLength ();
232 for(int i = 0; i < children_length; i++) {
233 Node node = children.item (i);
234 if(element == node) {
235 return i;
236 }
237 }
238 return -1;
239 }
240
241 public synchronized int getSize () {
242
243 if(children == null) {
244 children = root.getElementsByTagName (tag_name);
245 }
246 return children.getLength ();
247 }
248
249 public synchronized void refresh () {
250 fireContentsChanged (this, 0, getSize ());
251 }
252
253 public synchronized void refresh (DOMProxyListEntry entry) {
254 int index = indexOf (entry);
255 fireContentsChanged (this, index, index);
256 }
257
258 public synchronized void remove (DOMProxyListEntry entry) {
259 remove (indexOf (entry));
260 }
261
262 public synchronized void remove (int index) {
263 // Retrieve the required element
264 Node node = children.item (index);
265 // Find its parent
266 Node parent_node = node.getParentNode ();
267 // Now remove it
268 parent_node.removeChild (node);
269 // Refresh model
270 cache.clear ();
271
272 fireIntervalRemoved (this, index, index);
273 }
274
275
276 /** Changes the 'root' element that this list sources its information from.
277 * @param root the new root Element
278 */
279 public synchronized void setRoot (Element root) {
280 this.children = null;
281 cache.clear ();
282 this.root = root;
283 this.children = this.root.getElementsByTagName (this.tag_name);
284 fireContentsChanged (this, 0, getSize ());
285 }
286
287 public synchronized void setAssigned (boolean assigned) {
288 if (assigned) {
289 root.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.TRUE_STR);
290 }
291 else {
292 root.setAttribute (StaticStrings.ASSIGNED_ATTRIBUTE, StaticStrings.FALSE_STR);
293 }
294 }
295
296 public boolean isAssigned () {
297 return (root.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals ("") || root.getAttribute (StaticStrings.ASSIGNED_ATTRIBUTE).equals (StaticStrings.TRUE_STR));
298 }
299
300}
Note: See TracBrowser for help on using the repository browser.