source: other-projects/trunk/gs3-webservices-democlient/src/GS3DemoClient/org/greenstone/gs3client/data/NodeData.java@ 15222

Last change on this file since 15222 was 15222, checked in by ak19, 16 years ago

Greenstone3 web services demo-clientadded to GS3's other-projects

File size: 8.7 KB
Line 
1/**
2 *#########################################################################
3 * NodeData.java - part of the demo-client for Greenstone 3, of the
4 * Greenstone digital library suite from the New Zealand Digital Library
5 * Project at the * University of Waikato, New Zealand.
6 * <BR><BR>
7 * Copyright (C) 2008 New Zealand Digital Library Project
8 * <BR><BR>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 * <BR><BR>
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *########################################################################
19 */
20
21package org.greenstone.gs3client.data;
22
23import java.util.Iterator;
24import java.util.Set;
25import java.util.Map.Entry;
26
27import java.util.Vector;
28import java.util.Map;
29import java.util.HashMap;
30
31import org.w3c.dom.Element;
32import org.w3c.dom.Node;
33import org.w3c.dom.NodeList;
34import org.greenstone.gs3client.data.ClassifierNodeData;
35import org.greenstone.gsdl3.util.GSXML;
36
37/**
38 * Abstract superclass NodeData can represent either a the information in
39 * a &lt;classifierNode&gt; (stored in a ClassifierNodeData object) or in a
40 * &lt;documentNode&gt; (stored in a DocumentNodeData object).
41 * @author ak19
42*/
43public abstract class NodeData {
44 /** The unique nodeID identifying this documentNode or classificationNode */
45 public final String nodeID;
46
47 /** Since we are setting the descendents lazily (only setting the children
48 * each time), we have a little flag to indicate whether this node has
49 * any children. */
50 public final boolean hasChildren;
51 /** stores this NodeData's tag element: can be either
52 * &lt;documentNode&gt; or &lt;classifierNode&gt; */
53 protected final Element nodeTag;
54
55 /** Map of the metadata (name, value) pairs of this document-
56 * or classifier-node */
57 protected Map nodeMetadata = null;
58
59 /** @return an array of the children of this NodeData, however such a
60 * structure may be stored internally by a NodeData subclass. */
61 public abstract NodeData[] getChildren();
62
63 /** Constructor that extracts the nodeID value from the given nodeTag:
64 * &lt;classifierNode nodeID = "x" /&gt;
65 * or &lt;documentNode nodeID = "x" /&gt; */
66 public NodeData(Element nodeTag) {
67 this.nodeTag = nodeTag; // store this node's tag information. Useful
68 // for when we are setting the children of this NodeData
69 this.hasChildren = this.nodeTag.hasChildNodes();
70
71 // We'd definitely have the nodeID attribute, but to be on the safe
72 // side, check it's there first:
73 this.nodeID = nodeTag.hasAttribute(GSXML.NODE_ID_ATT) ?
74 nodeTag.getAttribute(GSXML.NODE_ID_ATT) : "";
75 }
76
77 /**
78 * Sets member metadataList if there is a &lt;metadataList&gt; subelement in
79 * docNodeTag: first get the &lt;metadataList&gt; then its &lt;metadata&gt;
80 * children
81 * @param nodeTag is a documentNode or classifierNode XML Element that
82 * contains metadata information which is used to set this NodeData object's
83 * metadata (if there are any, the HashMap nodeMetadata will be set). */
84 public void setMetadataList(Element nodeTag) {
85 NodeList metaList = nodeTag.getElementsByTagName(
86 GSXML.METADATA_ELEM);
87 // will return empty metaList collection if there's none, so check for
88 // size instead of null:
89 int size = metaList.getLength();
90 if(size > 0) {
91 if(nodeMetadata == null) // if we check for this, can call
92 // setMetadataList() on this DocNodeData obj many times
93 // - each time with different <metadata> name-val pairs
94 nodeMetadata = new HashMap(size);
95 for(int i = 0; i < size; i++) {
96 // we know each is an element, as we got all desc elements
97 // of this <documentNode> that are <metadata>
98 Element meta = (Element)metaList.item(i);
99 String name = meta.getAttribute(GSXML.NAME_ATT);
100 Node e = meta.getFirstChild();
101 // If not null, e should be a textNode now: get its value
102 String bodyText = (e == null) ? "" : (String)e.getNodeValue();
103 // nodeMetadata.put(name, bodyText);
104 if(nodeMetadata.containsKey(name)) {
105 // key already exists, get the array of values mapping to that
106 // metadata name (= key)
107 Vector values = (Vector)nodeMetadata.get(name);
108 // check if the last value is the same as
109 // what we're trying to insert
110 String value = (String)values.get(values.size()-1);
111 if(!value.equals(bodyText)) // don't add duplicates
112 // append the new metadata value to the vector v:
113 values.add(bodyText);
114 } else { // create a new (key, val) pair by creating a new vector
115 // (= value) mapping to the new key
116 Vector values = new Vector();
117 values.add(bodyText);
118 nodeMetadata.put(name, values);
119 }
120 }
121 }
122 }
123
124 /** Called when setting descendents lazily: only the children of this
125 * node are set. We don't care to setDescendents now, will set it later
126 * when necessary.
127 * @param v is an empty/non-null Vector which will, at method's end, contain
128 * all the Document- or ClassifierNodeData objects that are children of
129 * this NodeData object. */
130 protected void setChildren(Vector v, Map idsToNodes_map)
131 {
132 // first get all child elements of type docNode or classifierNode:
133 NodeList children = nodeTag.getChildNodes();
134 if(children.getLength() == 0)
135 return; // no children, this.childnodes remains at null
136
137 int size = children.getLength();
138 for(int i = 0; i < size; i++) {
139 Node n = children.item(i);
140 // For Element-nodes, getNodeName() returns the tag name.
141 // It *never* returns null for *any* Node type
142 if(n.getNodeName().equals(GSXML.CLASS_NODE_ELEM)) {
143 Element nodeElementTag = (Element)n;
144 if(!nodeElementTag.hasAttribute(GSXML.NODE_ID_ATT))
145 continue; // should not ever be the case
146 // skip any element that does not have a nodeID Attr
147
148 String id = nodeElementTag.getAttribute(GSXML.NODE_ID_ATT);
149 if(!idsToNodes_map.containsKey(id))
150 v.add(new ClassifierNodeData(nodeElementTag));
151 else
152 v.add(idsToNodes_map.get(id));
153 } else if(n.getNodeName().equals(GSXML.DOC_NODE_ELEM)) {
154 Element nodeElementTag = (Element)n;
155 if(!nodeElementTag.hasAttribute(GSXML.NODE_ID_ATT))
156 continue; // should not ever be the case
157 // skip any element that does not have a nodeID Attr
158
159 String id = nodeElementTag.getAttribute(GSXML.NODE_ID_ATT);
160 if(!idsToNodes_map.containsKey(id))
161 v.add(new DocumentNodeData(nodeElementTag));
162 else
163 v.add(idsToNodes_map.get(id));
164 } // else: tends to be an empty textNode ("#text"), skip that
165 }
166 }
167
168 /** @return a hashmap of this document's metadata (name, val) pairs.
169 * A null is returned if the nodeMetadata has not been set yet. */
170 public Map getMetadataList() { return nodeMetadata; }
171
172
173 /** @return the title of this docNodeData object, if any is set. If it's
174 * not been set yet (title metadata not yet set, a null is returned. */
175 public String getTitle() {
176 // Each metadata (like Title) may be an array of values.
177 // Here we return the first title in the array.
178 if(this.nodeMetadata != null && this.nodeMetadata.containsKey("Title"))
179 { // we know there's a title key now
180
181 Vector v = (Vector)this.nodeMetadata.get("Title");
182 return (String)v.get(0); // return first Title element
183 }
184 else return null; // when nodeMetadata == null or no Title key
185 }
186
187 /** @return the title of this docNodeData object, if any.
188 * Otherwise the nodeID is returned.
189 * This method is useful for displaying this docNodeData object as a
190 * node in a JTree. Some meaningful displayable value is returned,
191 * unlike getTitle() which returns a null if title is not set yet. */
192 public String toString() {
193 String title = getTitle();
194 return (title == null) ? this.nodeID : title;
195 }
196
197 /** @return the details contained in this NodeData object.
198 * Useful for debugging purposes. */
199 public String show() { return this.nodeID; }
200
201 /** @return a String representation of the contains of the
202 * nodeMetadata list (useful for debugging purposes). */
203 public String showMeta() {
204 StringBuffer buf = new StringBuffer();
205 if(nodeMetadata != null && !nodeMetadata.isEmpty()) {
206 buf.append("Metadata:\n");
207 Set entrySet = nodeMetadata.entrySet();
208 Iterator i = entrySet.iterator();
209 while(i.hasNext()) {
210 Entry entry = (Entry)i.next(); // Map.Entry
211 buf.append(" name: " + (String)entry.getKey() + " values: ");
212 Vector values = (Vector)entry.getValue();
213 for(int j = 0; j < values.size(); j++)
214 buf.append((String)values.get(j) + ", ");
215 buf.append("\n");
216 }
217 }
218 return buf.toString();
219 }
220}
Note: See TracBrowser for help on using the repository browser.