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 | */
|
---|
37 | package 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 |
|
---|
50 | import java.util.*;
|
---|
51 | import javax.swing.tree.*;
|
---|
52 | import org.greenstone.gatherer.Gatherer;
|
---|
53 | import org.greenstone.gatherer.msm.MSMUtils;
|
---|
54 | import org.greenstone.gatherer.util.Codec;
|
---|
55 | import org.greenstone.gatherer.util.StaticStrings;
|
---|
56 | import org.greenstone.gatherer.util.Utility;
|
---|
57 | import 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 | */
|
---|
61 | public 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 | }
|
---|