source: other-projects/gs3-webservices-java-client/trunk/src/GS3DemoClient/org/greenstone/gs3client/data/DocumentNodeData.java@ 26180

Last change on this file since 26180 was 26180, checked in by ak19, 12 years ago
  1. Fixed the democlient to work with the new GS3 again: lots of small things had got broken (such as image display, since the metadata being stored was different). 2. Updating the jar files and democlient distribution zip files with the latest working version of this.
File size: 24.9 KB
Line 
1/**
2 *#########################################################################
3 * DocumentNodeData.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.Vector;
25import java.util.Map;
26import java.util.HashMap;
27import java.util.Map.Entry;
28
29import org.w3c.dom.Element;
30import org.w3c.dom.Node;
31import org.w3c.dom.NodeList;
32import org.greenstone.gsdl3.util.GSXML;
33
34
35/**
36 * Represents the data stored in the &lt;documentNode&gt; Elements
37 * of Greenstone 3's XML response messages. A DocumentNodeData may
38 * have descendants of type DocumentNodeData. Some DocumentNodeData
39 * objects are the root of a structure, others are internal nodes or
40 * leaves.
41 * See p.47 to p.49 in the manual.
42 * @author ak19
43 */
44public class DocumentNodeData extends NodeData {
45 /** NodeType of this DocumentNodeData: root, internal or leaf */
46 public final String nodeType;
47 /** DocType can be Hierarchical for instance */
48 public final String docType;
49 /** Rank of this DocumentNodeData if the &lt;documentNode&gt;
50 * Element was returned in a search result */
51 public final double rank;
52
53 // not set initially, only set after calling
54 // setDescendentsOfRootNode(<nodeStructure>)
55 /** Reference to this doc's root */
56 protected DocumentNodeData rootDoc = null;
57 /** children of this node: part of &lt;nodeStructure&gt; Element */
58 protected DocumentNodeData[] childnodes = null;
59
60 /** A Hashmap to store &lt;nodeStructureInfo&gt; of a DocumentNodeData
61 * (if it has any) */
62 protected HashMap nodeStructureInfo_map = null;
63
64 /** The text content of the document */
65 protected String nodeContent = null;
66
67 /** Given tags of the form
68 * &lt;documentNode nodeID="HASHac0a04dd14571c60d7fbfd.4.2"
69 * nodeType="x" docType="y"&gt;
70 * &lt;nodeContent>Text&lt;/nodeContent&gt;
71 * &lt;nodeStructureInfo>&lt;info name="i" value="1" /&gt;
72 * &lt;info name = "ii" value = "2" /&gt;&lt;/nodeStructureInfo&gt;
73 * &lt;metadataList&gt;&lt;metadata name="a"&gt;Value
74 * &lt;/metadata&gt;&lt;/metadataList&gt;
75 * &lt;nodeStructure&gt;
76 * &lt;documentNode ....>&lt;/documentNode&gt;
77 * &lt;documentNode ....>&lt;/documentNode&gt;
78 * &lt;/nodeStructure&gt;
79 * &lt;/documentNode&gt;
80 * this constructor extracts the nodeId out of it and any other fields
81 * that might be set in the docNodeTag &lt;documentNode&gt; element.
82 * @param docNodeTag is an &lt;documentNode&gt; XML element to construct
83 * this DocumentNodeData object from
84 */
85 public DocumentNodeData(Element docNodeTag){
86 // We'd definitely have the nodeID attribute, but to be on the safe
87 // side:
88 super(docNodeTag);
89
90 // this.nodeType and this.docType will be set: these attributes are
91 // there in the <documentNode> elements of all Query Responses as
92 // well as in <documentNode>s of documentStructureRetrieve responses.
93 this.nodeType = docNodeTag.hasAttribute(GSXML.NODE_TYPE_ATT) ?
94 docNodeTag.getAttribute(GSXML.NODE_TYPE_ATT)
95 : GSXML.NODE_TYPE_ROOT; //DEFAULTING TO ROOT IF NONE SPECIFIED!
96
97 this.docType = docNodeTag.hasAttribute(GSXML.DOC_TYPE_ATT) ?
98 docNodeTag.getAttribute(GSXML.DOC_TYPE_ATT) : "";
99 // OR default to GSXML.DOC_TYPE_SIMPLE????
100
101 String rankVal = docNodeTag.hasAttribute(GSXML.NODE_RANK_ATT) ?
102 docNodeTag.getAttribute(GSXML.NODE_RANK_ATT) : "0";
103 this.rank = Double.parseDouble(rankVal);
104
105 // If <documentNode> has no <metadataList> child, then member variable
106 // metadataList remains null and can be set later if and as required.
107 setMetadataList(docNodeTag);
108
109 // structureInfo either initialised if there <documentNode> has a child
110 // element called <nodeStructureInfo>, else it remains null.
111 setNodeStructInfo(docNodeTag);
112
113 // Sets member nodeContent (the text content of the document) to the
114 // document's text if this <documentNode> has a child <nodeContent>.
115 // If there is no such child, nodeContent will be set to empty string.
116 setNodeContent(docNodeTag);
117 }
118
119 /** Given a &lt;nodeStructure&gt;&lt;/nodeStructure&gt; element returned
120 * from a request for the *ENTIRE* nodeStructure, this method will find the
121 * &lt;documentNode&gt; that is the Root (nodeType=ROOT) and from there
122 * on proceed to set all descendent &lt;documentNode&gt;s.
123 * If either the root or any descendent &lt;documentNode&gt;s have already
124 * been instantiated at any point during program execution, it will
125 * be reused, else a new object representing that descendent/root
126 * &lt;documentNode&gt; will be created.
127 * The nodeIDsToDocNodes_map is a mapping of nodeIDs to existing
128 * documentNodeData objects, so that the DocumentNodeData objects with
129 * the same ID need not be instantiated where they already exist.
130 * This method returns the rootNode if it completes successfully,
131 * otherwise it returns null.
132 * @param nodeStructure is the &lt;nodeStructure&gt;&lt;/nodeStructure&gt;
133 * element returned from a request for the *ENTIRE* nodeStructure
134 * @param nodeIDsToDocNodes_map is the Map of node IDs to DocumentNodeData
135 * objects being maintained
136 * @return the root DocumentNodeData object of the &lt;documentNode&gt;s
137 * in the &lt;nodeStructure&gt;
138 */
139 public DocumentNodeData setDescendentsOfRootNode(Element nodeStructure,
140 Map nodeIDsToDocNodes_map)
141 {
142 // First find <documentNode> inside <nodeStructure> where
143 // nodeType==ROOT. This always happens to be the first
144 // <documentNode> child of <nodeStructure>
145 // Use this root <docNode> to set its children and all descendents
146 // If there is no <docNode nodetype==ROOT>, return false.
147 Element rootDocNodeTag = ParseUtil.getFirstChildElementCalled(
148 nodeStructure, GSXML.DOC_NODE_ELEM);
149
150 // These cases shouldn't occur, but to be on the safe side -
151 // Actually, this happens with project gutenberg searches: where
152 // docType and nodeType are not set and the <nodeStructure>
153 // contains no child <documentNode>. In such cases, make this
154 // documentNodeData the root.
155 if(rootDocNodeTag == null) {
156 rootDoc = this;
157 return rootDoc;
158 }
159 String type = rootDocNodeTag.getAttribute(GSXML.NODE_TYPE_ATT);
160 if(!type.equals(GSXML.NODE_TYPE_ROOT)) {
161 rootDoc = this; // Case of first <docNode> of <nodeStructure>
162 return rootDoc; // nodetype != root -> this shouldn't happen
163 // but if there's only 1 node and it's a leaf, make it
164 // the root. This actually happens in simple image collections
165 // which have no substructures containing further images
166 //return null;
167 }
168 // We found the root node Element we want, get its NodeID,
169 // and then start processing the root node for descendents
170 String ID = rootDocNodeTag.hasAttribute(GSXML.NODE_ID_ATT) ?
171 rootDocNodeTag.getAttribute(GSXML.NODE_ID_ATT) : "";
172
173 // try to find this ID in HashMap of already instantiated
174 // documentNodeData objects - if it exists, set children
175 // on that. If it doesn't, then create new object and set
176 // the children+descendents on that. (Creating new object
177 // will automatically add it to the hashMap
178 DocumentNodeData root = null;
179 if(nodeIDsToDocNodes_map.containsKey(ID))
180 root = (DocumentNodeData)nodeIDsToDocNodes_map.get(ID);
181 else {
182 // not in HashMap, so create a new docNode (this will set
183 // nodeType and docType) and add it to the map
184 root = new DocumentNodeData(rootDocNodeTag);
185 nodeIDsToDocNodes_map.put(root.nodeID, root);
186 }
187
188 this.rootDoc = root;
189
190 // either way, we have a root node now, so set its children
191 root.setDescendents(root, rootDocNodeTag, nodeIDsToDocNodes_map);
192 // docNodeTag of root
193
194 return root;
195 }
196
197
198 /**
199 * Recursive method.
200 * Called by setDescendentsOfRootNode(). Given a docNodeTag (of the Root)
201 * which was nested within a &lt;nodeStructure&gt; element, this method sets
202 * all the descendents of that root. This means that each documentNodeData
203 * object in the hierarchy of the root will have its childnodes[] variable
204 * set, iff that object is not a nodeType==LEAF. With leaves, the
205 * childnodes array will remain null.
206 * The nodeIDsToDocNodes_map is a mapping of nodeIDs to existing
207 * documentNodeData objects, so that the DocumentNodeData objects with the
208 * same ID need not be instantiated where they already exist.
209 * @param root - the root element of this documentNodeData
210 * @param docNodeTag - the &lt;documentNode&gt; XML Element of the Root
211 * nested within a &lt;nodeStructure&gt; element
212 * @param nodeIDsToDocNodes_map is the Map of node IDs to DocumentNodeData
213 * objects being maintained
214 */
215 protected void setDescendents(DocumentNodeData root, Element docNodeTag,
216 Map nodeIDsToDocNodes_map)
217 {
218 if(this.nodeType.equals(GSXML.NODE_TYPE_LEAF))
219 return; // no children
220
221 Vector children = ParseUtil.getAllChildElementsCalled(
222 docNodeTag, GSXML.DOC_NODE_ELEM);
223 if(children == null) // shouldn't have to check this, as the check
224 // on nodeType==LEAF above would have been enough
225 return; // no children, hence no descendents
226
227 // else, obtain and instantiate DocumentNodeData objects
228 // on each of the children
229 this.childnodes = new DocumentNodeData[children.size()];
230 for(int i = 0; i < childnodes.length; i++) {
231 Element childDocNodeTag = (Element)children.get(i);
232 String ID = childDocNodeTag.hasAttribute(GSXML.NODE_ID_ATT) ?
233 childDocNodeTag.getAttribute(GSXML.NODE_ID_ATT) : "";
234
235 if(nodeIDsToDocNodes_map.containsKey(ID))
236 childnodes[i]
237 = (DocumentNodeData)nodeIDsToDocNodes_map.get(ID);
238 else { //not yet in the map of documentNodeData objects, so
239 // create a new DocumentNodeData and add it to the map
240 childnodes[i] = new DocumentNodeData(childDocNodeTag);
241 nodeIDsToDocNodes_map.put(childnodes[i].nodeID, childnodes[i]);
242 }
243 // set the root for the descendent:
244 childnodes[i].rootDoc = root;
245 // Now set its children and so on until all descendents indicated
246 // in the <nodestructure><documentNode /></nodestructure> have
247 // been set.
248 childnodes[i].setDescendents(
249 root, childDocNodeTag, nodeIDsToDocNodes_map);
250 }
251 }
252
253 /* Can call these methods later as well (after constructor). If the
254 * docNodeTag passed to the constructor did not have these attributes,
255 * can set them later with a docNodeTag of the same nodeID that does
256 * have these attributes set. */
257
258 /** Sets structureInfo member variable &lt;nodeStructureInfo&gt; element is
259 * present as child of &lt;documentNode&gt;, else value of structureInfo
260 * remains unchanged. A &lt;docNode&gt; has no more than one child
261 * &lt;nodeStructureInfo&gt; in a response to a DocumentStructureRetrieve.
262 * However, the response can contain many such &lt;docNodes&gt;.
263 * See manual p.49.
264 * @param docNodeTag is the &lt;documentNode&gt; XML element containing
265 * the &lt;nodeStructureInfo&gt; Element that is to be processed */
266 public void setNodeStructInfo(Element docNodeTag) {
267 NodeList nl = docNodeTag.getElementsByTagName(
268 GSXML.NODE_STRUCTURE_ELEM+GSXML.INFO_ATT);
269 if(nl.getLength() > 0) {
270 // get the first <nodeStructureInfo> (which will be the only
271 // <nodeStructureInfo> for this <docNode>
272 Element nodeStructInfoTag = (Element)nl.item(0);
273 nl = null;
274 // Get any children <info> tags and extract data-values from them
275 nl = nodeStructInfoTag.getElementsByTagName("info");
276 int size = nl.getLength();
277 if(size > 0) {
278 nodeStructureInfo_map = new HashMap(size);
279 for(int i = 0; i < size; i++) {
280 Element infoTag = (Element)nl.item(i);
281 String name = infoTag.hasAttribute(GSXML.NAME_ATT) ?
282 infoTag.getAttribute(GSXML.NAME_ATT) : "";
283 String value = infoTag.hasAttribute(GSXML.VALUE_ATT) ?
284 infoTag.getAttribute(GSXML.VALUE_ATT) : "";
285 nodeStructureInfo_map.put(name, value);
286 }
287 }
288 }
289 // in all other cases, nodeStructureInfo_map remains null
290 }
291
292 /** Sets member variable nodeContent with the text (if any) inside any
293 * &lt;nodeContent&gt;&lt;/nodeContent&gt; child element of
294 * &lt;documentNode&gt;, else the value of nodeContent is set to empty
295 * string (""). The empty string will prevent it from being retrieved again
296 * and again (which would happen if nodeContent remained at null) if it had
297 * already been retrieved once.
298 * However, if the docNodeTag parameter is not the response from
299 * a documentContentRetrieve (if it doesn't have the proper XML
300 * structure for that), nodeContent remains null and can be set
301 * in future when given an appropriate docNodeTag.
302 * @param docNodeTag is the &lt;documentNode&gt; XML element containing
303 * the content information for this DocumentNodeData object */
304 public void setNodeContent(Element docNodeTag) {
305 Element nodeContentTag = ParseUtil.getFirstChildElementCalled(
306 docNodeTag, GSXML.NODE_CONTENT_ELEM);
307 if(nodeContentTag != null) { //such a child tag exists
308 //obtain its child textNode and the value thereof
309 Node content = nodeContentTag.getFirstChild();
310 // content will be null if <nodeContent /> instead of
311 // <nodeContent></nodeContent>
312 this.nodeContent
313 = (content == null) ? "" : content.getNodeValue();
314
315 // Now to fix the html if it's not already proper:
316 if(nodeContent.startsWith("<Sec>")) { // remove starting <Sec>
317 // it's not a recognised tag in html
318 nodeContent = nodeContent.substring(5);
319 nodeContent = nodeContent.trim();
320 if(nodeContent.startsWith("</")) {
321 // first closing bracket
322 int index = nodeContent.indexOf(">");
323 // remove any starting </B> or </I>
324 nodeContent = nodeContent.substring(index+1);
325 nodeContent = nodeContent.trim();
326 }
327 }
328 // Finally, make sure it has the proper starting (and ending tags)
329 if((!nodeContent.startsWith("<html>"))
330 || (!nodeContent.startsWith("<HTML>"))) {
331 nodeContent = "<html><head></head><body>"
332 + nodeContent + "</body></html>";
333 }
334 }
335 // else leave nodeContent as null, docNodeTag was not returned
336 // as the result of a docContentRetrieve response
337 }
338
339
340 /** @return the data stored in this DocumentNodeData object, all except
341 * the document content which can be accessed by calling toString().
342 * This method is useful for debugging purposes: to view what each
343 * field's values are. */
344 public String show() {
345 StringBuffer buf = new StringBuffer("nodeID: " + this.nodeID);
346 buf.append(" nodeType: " + this.nodeType);
347 buf.append(" docType: " + this.docType);
348
349 if(nodeStructureInfo_map != null) {
350 buf.append("NodeStructureInfo:");
351 Iterator i = nodeStructureInfo_map.entrySet().iterator();
352 while(i.hasNext()) {
353 Entry e = (Entry)i.next();
354 buf.append("\nname: " + (String)e.getKey());
355 buf.append(" value: " + (String)e.getValue());
356 }
357 }
358 buf.append("\n");
359 buf.append(showMeta());
360 return buf.toString();
361 }
362
363 /** @return true if the (nodeType of) this DocumentNodeData is a leaf */
364 public boolean isLeaf() { return nodeType.equals(GSXML.NODE_TYPE_LEAF); }
365
366 /* Accessor methods */
367 /** @return the nodeType of this DocumentNodeData */
368 public String getNodeType() { return nodeType; }
369 /** @return the docType of this DocumentNodeData */
370 public String getDocType() { return docType; }
371
372 /** @return the root of the structure of which this documentNodeData
373 * is part (this docNodeData is either the root itself or its child
374 * or descenedent). A null is returned if the Root docNode and its
375 * descendents have not been set yet. */
376 public DocumentNodeData getRoot() { return this.rootDoc; }
377
378 /** @return this document's text content (which may be empty string
379 * if there was none). It will return null if the nodeContent has
380 * not been set yet. */
381 public String getContent() { return nodeContent; }
382
383 /** @return an array of all this DocNode's children. Each childnode
384 * in turn, can further contain children, etc. Null is returned if
385 * there are no childnodes or if setDescendentsOfRootNode() has not
386 * been called (that is, if the root has not yet been set). */
387 public DocumentNodeData[] getDescendents() { return childnodes; }
388
389 /** @return gets the children (NodeData) of this DocumentNodeData
390 * but does not guarantee that their children are set. That is,
391 * it's possible that this DocumentNodeData's children may have
392 * children of their own but that these may not be set yet (and
393 * are temporarily still null). */
394 public NodeData[] getChildren() { return childnodes; }
395
396 /** When called on a rootNode, returns an array of all the descendents'
397 * nodeIDs. If this object is not a rootNode, it returns null.
398 * Parameter onlyTheUntitled, if true, makes this method return only the
399 * nodeIDs of those documentNodeData descendents for whom the title has
400 * not yet been set.
401 * If false, the nodeIDs of all dDcumentNodeData descendents will be
402 * returned, regardless of whether their titles are already set.
403 * @param onlyTheUntitled - if true this method is only to return those
404 * descendants' IDs whose titles have not yet been set. If false,
405 * all descendants' nodeIDs are returned.
406 * @return an array of all the descendant DocumentNodeData's NodeIDs */
407 public String[] getDescNodeIDsAsList(boolean onlyTheUntitled) {
408 String[] nodeIDs = null;
409 if(this.nodeType.equals(GSXML.NODE_TYPE_ROOT)) {
410 Vector v = new Vector();
411 if(!onlyTheUntitled || this.getTitle() == null)
412 v.add(this.nodeID); // add root only if its title not yet set
413 descNodeIDsAsList(v, this, onlyTheUntitled);
414 if(v.size() > 0) {
415 nodeIDs = new String[v.size()];
416 v.toArray(nodeIDs);
417 } // else if v.size() == 0, this method will return null
418 }
419 return nodeIDs;
420 }
421
422 /** Recursive method that adds all the nodeIDs of the descendents
423 * of DocumentNodeData parent into the Vector v.
424 * If parameter onlyTheUntitled=true, then only the nodeIDs of the
425 * untitled DocumentNodeData descendents are added in. Otherwise,
426 * all descendents' nodeIDs are.
427 * @param v is the Vector being populated with descendant documentNodeData's
428 * IDs.
429 * @param parent is the parent DocumentNodeData node currently being
430 * considered in this recursion step.
431 * @param onlyTheUntitled should be true if only those descendant
432 * DocumentNodeData objects that don't yet have a title need to be returned.
433 * If false, it returns all descendants' nodeIDs in the Vector v. */
434 protected static void descNodeIDsAsList(Vector v,
435 DocumentNodeData parent, boolean onlyTheUntitled)
436 {
437 // Recursion
438 // Base case:
439 if(parent.childnodes == null)
440 return;
441 for(int i = 0; i < parent.childnodes.length; i++) {
442 // Now comes step that does actual processing:
443
444 // if only asking for NodeIDs of descendents whose titles
445 // aren't set yet, then:
446 if(!onlyTheUntitled || parent.childnodes[i].getTitle() == null)
447 v.add(parent.childnodes[i].nodeID);
448 // above if-stmt should add the desc nodeID for either
449 // - all descendents (if onlyTheUntitled=true); or
450 // - otherwise, only for those whose title is not set yet
451
452 // Recursion step:
453 DocumentNodeData.descNodeIDsAsList(
454 v, parent.childnodes[i], onlyTheUntitled);
455 }
456 }
457
458 /** @return true if this documentNode's root is associated with the
459 * ImagePlug or PagedImgPlug.
460 * @see <a href="http://wiki.greenstone.org/wiki/gsdoc/tutorial/en/scanned_image_collection.htm">The scanned image collection, for names of Plugin metadata values PagedImgPlug and ImagePlug</a> */
461 public boolean canBeImage() {
462 if(this.rootDoc == null) {
463 return false;
464 }
465 // else
466 if(!this.rootDoc.nodeMetadata.containsKey("Plugin")) {
467 return false; // this shouldn't happen:
468 // I think every root has Plugin meta
469 }
470 // else
471 Vector values = (Vector)this.rootDoc.nodeMetadata.get("Plugin");
472 String plugin = (String)values.get(0);
473
474 final String imagePlug = "PagedImgPlug";
475 final String pagedImgPlug = "ImagePlug";
476 if(plugin.equals(pagedImgPlug) || plugin.equals(imagePlug))
477 return true;
478 else
479 return false;
480 }
481
482 /** @return value of "notext" metadata field, if any. If true, this
483 * indicates that the document is purely an image. Otherwise it indicates
484 * that there is both a text view and an image view associated with this
485 * document. */
486 public boolean hasNoText() {
487 if(this.nodeMetadata == null)
488 return false; // deal with any odd cases
489
490 if(!this.nodeMetadata.containsKey("NoText"))
491 return false; // no NoText metadata, so it probably has text
492 Vector values = (Vector)this.nodeMetadata.get("NoText");
493 String noText = (String)values.get(0);
494 int val = Integer.parseInt(noText);
495 return (val == 1); // 0 if it has text, 1 if indeed it has no text
496 }
497
498 /** @return the image url stored in the "srcicon" metadata field, if any. */
499 public String getImgURL() {
500 if(this.nodeMetadata == null)
501 return ""; // deal with any odd cases
502
503 String imgMetaFound = "";
504 String srclinkFile = nodeMetadata.containsKey("srclinkFile") ? (String)((Vector)nodeMetadata.get("srclinkFile")).get(0) : "";
505 String w = nodeMetadata.containsKey("ImageWidth") ? (String)((Vector)nodeMetadata.get("ImageWidth")).get(0) : "";
506 String h = nodeMetadata.containsKey("ImageHeight") ? (String)((Vector)nodeMetadata.get("ImageHeight")).get(0) : "";
507
508 if(this.nodeMetadata.containsKey("srcicon")) {
509 imgMetaFound = "srcicon";
510 }
511 else if(this.nodeMetadata.containsKey("srclink")) { // old Greenstone 3
512 imgMetaFound = "srclink";
513 }
514 else {
515 return "";
516 }
517 Vector values = (Vector)this.nodeMetadata.get(imgMetaFound);
518 String imgTag = (String)values.get(0);
519
520 if(imgMetaFound.equals("srcicon")) {
521 imgTag = imgTag.replace("[srclinkFile]", srclinkFile);
522 imgTag = imgTag.replace("[ImageWidth]", w);
523 imgTag = imgTag.replace("[ImageHeight]", h);
524 return imgTag;
525 }
526
527 // else deal with srclink in the old Greenstone 3 way:
528
529 // now we got <a href="somelink">; extract just the "somelink" portion
530 int startindex = imgTag.indexOf('\"');
531 int endindex = imgTag.lastIndexOf('\"');
532 imgTag = imgTag.substring(startindex, endindex+1);
533
534 // remove the macro - if present - and replace it with the
535 // assocFilePath mentioned in the document's root's metadata
536 startindex = imgTag.indexOf('[');
537 if(startindex != -1 && imgTag.contains("assocfilepath")) {
538 if(this.rootDoc == null) // need root doc to get assocfilepath
539 return "";
540 // else
541 endindex = imgTag.indexOf(']');
542 imgTag = imgTag.substring(0, startindex)
543 + getAssocFilePath()
544 + imgTag.substring(endindex+1, imgTag.length());
545 }
546 return imgTag;
547 }
548
549 /** @return the Source metadata value which represents the image file
550 * name. Returns "" if this DocumentNodeData is not a root or does not
551 * have Source meta. */
552 public String getImgName() {
553 if(this.rootDoc == null)
554 return "";
555 // else
556 if(!this.nodeMetadata.containsKey("Source"))
557 return "";
558 // else
559 Vector values = (Vector)this.nodeMetadata.get("Source");
560 return (String)values.get(0);
561 }
562
563 /** @return the vector of values for metadata name "gsdlassocfile": a vector
564 * of MetaPairs(filename, mimetype).
565 * An empty vector is returned for all docNodes other than the root. And the
566 * root too need not always have associated files listed in its metadata. */
567 public Vector getAssociatedFileNames() {
568 Vector v = new Vector();
569 final char COLON = ':';
570 if(this.nodeMetadata.containsKey("gsdlassocfile")) {
571 Vector assocFileNames = (Vector)nodeMetadata.get("gsdlassocfile");
572 for(int i = 0; i < assocFileNames.size(); i++) {
573 // assocFileNames are stored in format "cover.jpg:image/jpeg:"
574 // need to split these to separate the name from the mimetype
575 String filename = (String)assocFileNames.get(i);
576 int firstColon = filename.indexOf(COLON);
577 String mimetype = filename.substring(
578 firstColon+1, filename.lastIndexOf(COLON));
579 filename = filename.substring(0, firstColon);
580 Pair p = new Pair(filename, mimetype);
581 // (we're not going to be sorting these pairs, so we make
582 // no use of each Pair's Comparable nature)
583 v.add(p);
584 }
585 }
586 return v; // returns empty vector if no gsdlassocfile metadata
587 }
588
589 /** @return the root document's assocfilepath metadata field, if any.
590 * This will indicate the directory path where the associated images
591 * and other files are stored. */
592 public String getAssocFilePath() {
593 if(this.rootDoc == null)
594 return "";
595 // else, check for rootDoc having "assocfilepath" metadata:
596 if(!rootDoc.nodeMetadata.containsKey("assocfilepath"))
597 return "";
598 Vector values = (Vector)rootDoc.nodeMetadata.get("assocfilepath");
599 return (String)values.get(0);
600 }
601}
Note: See TracBrowser for help on using the repository browser.