source: trunk/gli/src/org/greenstone/gatherer/valuetree/GValueNode.java@ 7529

Last change on this file since 7529 was 7529, checked in by mdewsnip, 20 years ago

Why was the value tree case-insensitive?!?

  • Property svn:keywords set to Author Date Id Revision
File size: 12.5 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 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.valuetree;
38
39/**
40 * Title: The Gatherer<br>
41 * Description: The Gatherer: a tool for gathering and enriching digital collections.<br>
42 * Copyright: Copyright (c) 2001<br>
43 * Company: The University of Waikato<br>
44 * First Coded: 20/06/02
45 * Revised:<br>
46 * @author John Thompson, Greenstone Digital Libraries
47 * @version 2.1
48 */
49
50import java.util.*;
51import javax.swing.tree.*;
52import org.greenstone.gatherer.Gatherer;
53import org.greenstone.gatherer.msm.MSMUtils;
54import org.greenstone.gatherer.util.Codec;
55import org.greenstone.gatherer.util.StaticStrings;
56import org.greenstone.gatherer.util.Utility;
57import org.w3c.dom.*;
58
59/** This class is instantiated using a metadata element. From this parent element, which refers to a specific Element in the mds DOM model, the AssignedValues child is used as the root of a tree data-structure encompassing all of the nodes within the AssignedValues tree. This class also provide methods for adding, updating and removing nodes within this tree, as well as implementing all of the methods necessary for this node to be used as the basis of a tree model.
60 */
61public class GValueNode
62 extends DefaultMutableTreeNode {
63
64 static final public int DOM = 0;
65 static final public int GREENSTONE = 1;
66 static final public int TEXT = 2;
67
68 private String element_name = null;
69 private String default_value = null;
70
71 public GValueNode(Element element) {
72 this.children = null;
73 this.userObject = element;
74 this.default_value = null;
75 }
76
77 public GValueNode(String element_name, String default_value) {
78 this.element_name = element_name;
79 this.default_value = default_value;
80 }
81
82 /** Compares two GValueNodes for ordering by using the String.compareTo method.
83 * @param sibling The <strong>Object</strong> representing the GValueNode we are comparing ourselves to.
84 * @return An <i>int</i> indicating the ordering. The value is less than zero if we are before the parameter object, zero if we are equal and greater than zero if we preceed sibling.
85 */
86 public int compareTo(Object sibling) {
87 return toString().compareTo(sibling.toString());
88 }
89
90 /** Determine if this tree node contains a child with a matching value.
91 * @param value The value we are attempting to match, as a <strong>String</strong>.
92 * @return <i>true</i> if there is a matching child node, <i>false</i> otherwise.
93 */
94 /* private boolean containsValue(String value) {
95 if(default_value != null) {
96 return false;
97 }
98 return getValue(value) != null;
99 } */
100
101 /** Returns an enumeration of the child nodes.
102 * @return An <strong>Enumeration</strong> containing the child nodes.
103 */
104 public Enumeration children() {
105 if(default_value != null) {
106 return null;
107 }
108 if(children == null) {
109 map();
110 }
111 return children.elements();
112 }
113 public boolean equals(Object other) {
114 return compareTo(other) == 0;
115 }
116
117 public GValueNode get(int index) {
118 GValueNode result = null;
119 if(children != null) {
120 result = (GValueNode) children.get(index);
121 }
122 return result;
123 }
124
125 /** Returns <I>true</I> if the reciever allows children. */
126 public boolean getAllowsChildren() {
127 return true;
128 }
129
130 /** Returns the child <I>TreeNode</I> at index <I>childIndex</I>.*/
131 public TreeNode getChildAt(int index) {
132 if(default_value != null) {
133 return this;
134 }
135 if(children == null) {
136 map();
137 }
138 return (GValueNode) children.get(index);
139 }
140
141 /** Returns the number of children <I>TreeNode</I>s the reciever contains. */
142 public int getChildCount() {
143 int size = 0;
144 if(default_value != null) {
145 size = 0;
146 }
147 if(children == null) {
148 map();
149 }
150 return children.size();
151 }
152
153 public Element getElement() {
154 return (Element) userObject;
155 }
156
157 /** Return the path to this node within the value tree model.
158 * @return A <strong>String</strong> representing the path, ie "Titles\Modern\The Green Mile"
159 */
160 public String getFullPath(boolean as_text) {
161 if(default_value != null) {
162 return default_value;
163 }
164 StringBuffer path = new StringBuffer(toString(DOM));
165 GValueNode node = (GValueNode) getParent();
166 while(node != null && !node.getElement().getNodeName().equalsIgnoreCase("AssignedValues")) {
167 path.insert(0, StaticStrings.PIPE_STR);
168 path.insert(0, node.toString(DOM));
169 node = (GValueNode) node.getParent();
170 }
171 if(as_text) {
172 String temp = path.toString(); ///odec.transform(path.toString(), codec.GREENSTONE_TO_TEXT);
173 ///ystem.err.println("Raw: " + temp);
174 temp = Codec.transform(temp, Codec.DECODE_PATH);
175 temp = Codec.transform(temp, Codec.DECODE_SQUARE_BRACKETS);
176 ///ystem.err.println("Decoded: " + temp);
177 return temp;
178 }
179 else {
180 return path.toString();
181 }
182 }
183
184 /** Returns the index of <I>node</I> in the recievers children. If the
185 * reciever does not contain <I>node</I>, <I>-1</I> will be returned. */
186 public int getIndex(TreeNode node) {
187 if(default_value != null) {
188 return 0;
189 }
190 if(children == null) {
191 map();
192 }
193 return children.indexOf(node);
194 }
195
196 public String getMetadataElementName() {
197 if(default_value != null) {
198 return element_name;
199 }
200 GValueNode node = this;
201 while(node != null && !node.getElement().getNodeName().equalsIgnoreCase("AssignedValues")) {
202 node = (GValueNode)node.getParent();
203 }
204 if(node != null) {
205 return node.getElement().getAttribute("element");
206 }
207 return null;
208 }
209
210
211 public GValueNode getValue(String value)
212 {
213 ///ystem.err.println("GValueNode.getValue(" + value + ")");
214 if (default_value != null) {
215 return this;
216 }
217
218 if (children == null) {
219 map();
220 }
221
222 for (int i = 0; i < children.size(); i++) {
223 GValueNode child = (GValueNode) children.get(i);
224 // System.err.println("Comparing " + value + " and " + child.toString(GValueNode.DOM));
225 if (value.equals(child.toString(GValueNode.DOM))) {
226 return child;
227 }
228 }
229
230 return null;
231 }
232
233
234 /** Adds <I>child</I> to the receiever at <I>index</I>. <I>child</I> will
235 * be messaged with setParent().
236 */
237 public void insert(MutableTreeNode child, int index) {
238 if(default_value != null) {
239 return;
240 }
241 if(index >= children.size()) {
242 // Append to children.
243 children.add(child);
244 // And to document
245 getElement().appendChild(((GValueNode)child).getElement());
246 }
247 else {
248 GValueNode sibling = (GValueNode) children.get(index);
249 // Insert in children
250 children.add(index, child);
251 // And in document
252 getElement().insertBefore(((GValueNode)child).getElement(), sibling.getElement());
253 }
254 child.setParent(this);
255 }
256
257 /** Returns <I>true</I> if the reciever is a leaf. */
258 public boolean isLeaf() {
259 if(default_value != null || getChildCount() > 0) {
260 return false;
261 }
262 return true;
263 }
264
265 /** Ensure that the children nodes of this tree are instantiated, and record the initial mappings for legacy sake.
266 * @param mapping A <strong>HashMap</strong> into which to write the initial mappings.
267 * @param prefix The prefix to use for indexes, as a <strong>String</strong>.
268 */
269 public void map(HashMap mapping, String prefix) {
270 if(default_value != null) {
271 return;
272 }
273 children = new Vector();
274 if(prefix.length() > 0) {
275 prefix = prefix + ".";
276 }
277 int i = 1;
278 for(Node node = getElement().getFirstChild(); node != null; node = node.getNextSibling()) {
279 if(node.getNodeName().equals("Subject")) {
280 GValueNode child = new GValueNode((Element)node);
281 child.setParent(this);
282 children.add(child);
283 String index = prefix + i;
284 mapping.put(index, child);
285 child.map(mapping, index);
286 i++;
287 }
288 }
289 }
290
291 /** Resets the user object of the reciever to <I>object</I>. */
292 public void setUserObject(Object object) {
293 // Can't ever change Elements from here. Have to use editor. */
294 }
295
296 public void setValue(String value) {
297 setNodeValue("Value", value);
298 }
299
300 public int size() {
301 int size = 0;
302 if(children != null) {
303 size = children.size();
304 }
305 return size;
306 }
307
308 /** Returns a <I>String</I> representation of the reciever. If this
309 * happens to be the AssignedValues 'root' then we do something slightly
310 * different, otherwise we return the value of the <I>#Text</I> child of
311 * the <I>Value</I> of this <I>Subject</I> node!
312 */
313 public String toString() {
314 return toString(GValueNode.TEXT);
315 }
316
317 public String toString(int decode_type) {
318 if(default_value != null) {
319 return default_value;
320 }
321 Element element = getElement();
322 String name = element.getNodeName();
323 String result = null;
324 if(name.equals("Subject")) {
325 result = MSMUtils.getValue(element);
326 ///ystem.err.print(result);
327 switch(decode_type) {
328 case GValueNode.GREENSTONE:
329 // We want this as greenstone format
330 ///ystem.err.print(result);
331 //result = /odec.transform(result, /odec.DOM_TO_GREENSTONE);
332 ///ystem.err.println(" -> D2G decode -> " + result);
333 break;
334 case GValueNode.TEXT:
335 //result = /odec.transform(result, /odec.DOM_TO_TEXT);
336 result = Codec.transform(result, Codec.DECODE_PATH);
337 result = Codec.transform(result, Codec.DECODE_SQUARE_BRACKETS);
338 ///ystem.err.println(" -> D2T decode -> " + result);
339 break;
340 default:
341 ///ystem.err.println(result + " -> nothing to do.");
342 }
343 }
344 else if(name.equals("AssignedValues")) {
345 result = getMetadataElementName();
346 }
347 return result;
348 }
349
350 private void map() {
351 children = new Vector();
352 for(Node node = getElement().getFirstChild(); node != null; node = node.getNextSibling()) {
353 if(node.getNodeName().equals("Subject")) {
354 GValueNode child = new GValueNode((Element)node);
355 child.setParent(this);
356 children.add(child);
357 }
358 }
359 }
360
361 /** Removes the child at index from the receiver. */
362 public void remove(int index) {
363 remove((MutableTreeNode)getChildAt(index));
364 }
365
366 /** Removes node from the receiver. */
367 public void remove(MutableTreeNode node) {
368 children.remove(node);
369 node.setParent(null);
370 // Remove from DOM
371 Element child_element = ((GValueNode)node).getElement();
372 Node parent_node = child_element.getParentNode();
373 parent_node.removeChild(child_element);
374 }
375
376 /** Removes the receiver from its parent. */
377 public void removeFromParent() {
378 if(parent != null) {
379 parent.remove(this);
380 }
381 }
382
383 private void setNodeValue(String name, String value) {
384 boolean found = false;
385 // Attempt to retrieve a child node named name
386 Element element = (Element) userObject;
387 for(Node pos_node = element.getFirstChild(); pos_node != null; pos_node = pos_node.getNextSibling()) {
388 // And if we find such a node
389 if(pos_node.getNodeName().equals(name)) {
390 // And the new value is non-null, retrieve its text node and change it.
391 if(value != null) {
392 for(Node pos_text = pos_node.getFirstChild(); pos_text != null; pos_text = pos_text.getNextSibling()) {
393 // When we find the node...
394 if(pos_text.getNodeName().equals("#text")) {
395 pos_text.setNodeValue(value);
396 }
397 }
398 }
399 // Otherwise remove the node altogether
400 else {
401 element.removeChild(pos_node);
402 }
403 found = true;
404 }
405 }
406 // Otherwise if no such node exists add it.
407 if(!found && value != null) {
408 Document document = element.getOwnerDocument();
409 Node new_node = document.createElementNS("", name);
410 element.appendChild(new_node);
411 Node new_text = document.createTextNode(value);
412 new_node.appendChild(new_text);
413 new_text = null;
414 new_node = null;
415 }
416 // Done.
417 element = null;
418 return;
419 }
420}
Note: See TracBrowser for help on using the repository browser.