source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java@ 25658

Last change on this file since 25658 was 25658, checked in by sjm84, 12 years ago

Bought over the xmlNodeToString function from XMLTools (GLI) and also added functions to help with the on-page xml viewing

  • Property svn:keywords set to Author Date Id Revision
File size: 39.2 KB
Line 
1/*
2 * GSXML.java
3 * Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19package org.greenstone.gsdl3.util;
20
21import org.w3c.dom.NamedNodeMap;
22import org.w3c.dom.Node;
23import org.w3c.dom.Element;
24import org.w3c.dom.NodeList;
25import org.w3c.dom.Document;
26import org.w3c.dom.Text;
27
28import javax.xml.transform.TransformerFactory;
29import javax.xml.transform.Transformer;
30
31import java.io.Serializable;
32import java.io.StringWriter;
33import javax.xml.transform.stream.StreamResult;
34import javax.xml.transform.dom.DOMSource;
35import javax.xml.transform.OutputKeys;
36
37import java.util.Map;
38import java.util.Set;
39import java.util.HashMap;
40import java.util.Vector;
41import java.util.Iterator;
42import java.util.ArrayList;
43
44//import java.util.Locale;
45
46import org.apache.log4j.*;
47
48/** various functions for extracting info out of GS XML */
49public class GSXML
50{
51
52 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSXML.class.getName());
53
54 // greenstone message xml elements
55 public static final String MESSAGE_ELEM = "message";
56 public static final String REQUEST_ELEM = "request";
57 public static final String RESPONSE_ELEM = "response";
58 public static final String COLLECTION_ELEM = "collection";
59 public static final String SERVICE_ELEM = "service";
60 public static final String CLUSTER_ELEM = "serviceCluster";
61 public static final String SITE_ELEM = "site";
62 public static final String PARAM_ELEM = "param";
63 public static final String PARAM_OPTION_ELEM = "option";
64 public static final String CONTENT_ELEM = "content";
65 public static final String RESOURCE_ELEM = "resource";
66 public static final String DOCUMENT_ELEM = "document";
67 public static final String METADATA_ELEM = "metadata";
68 public static final String SERVICE_CLASS_ELEM = "serviceRack";
69 public static final String CLASSIFIER_ELEM = "classifier";
70 public static final String APPLET_ELEM = "applet";
71 public static final String APPLET_DATA_ELEM = "appletData";
72 public static final String CONFIGURE_ELEM = "configure";
73 public static final String STATUS_ELEM = "status";
74 public static final String ERROR_ELEM = "error";
75 public static final String DEFAULT_ELEM = "default";
76 public static final String STYLESHEET_ELEM = "format";//"stylesheet"; // any additional stylesheet stuff is carried in the message inside this elem
77 public static final String FORMAT_ELEM = "format"; // config files use format - should we use this instead of stylesheet??
78 public static final String TERM_ELEM = "term";
79 public static final String STOPWORD_ELEM = "stopword";
80 public static final String SYSTEM_ELEM = "system";
81 public static final String FORMAT_STRING_ELEM = "formatString";
82
83 //config file elems
84 public static final String COLLECTION_CONFIG_ELEM = "collectionConfig";
85 public static final String COLLECTION_BUILD_ELEM = "buildConfig";
86 public static final String COLLECTION_INIT_ELEM = "collectionInit";
87 public static final String RECOGNISE_ELEM = "recognise";
88 public static final String DOC_TYPE_ELEM = "docType";
89 public static final String SEARCH_ELEM = "search";
90 public static final String INFODB_ELEM = "infodb";
91 public static final String INDEX_ELEM = "index";
92 public static final String INDEX_STEM_ELEM = "indexStem";
93 public static final String INDEX_OPTION_ELEM = "indexOption";
94 public static final String BROWSE_ELEM = "browse";
95 public static final String DISPLAY_ELEM = "display";
96 public static final String LEVEL_ELEM = "level";
97 public static final String REPLACE_ELEM = "replace";
98
99 public static final String DBINFO_ELEM = "dbInfo";
100 public static final String DBNAME_ATT = "dbname";
101 public static final String DBPATH_ATT = "dbpath";
102 public static final String SQLSTATE_ATT = "sqlstate";
103 public static final String DATABASE_TYPE_ELEM = "databaseType";
104 public static final String SHORTNAME_ATT = "shortname";
105 public static final String NOTIFY_ELEM = "notify";
106 public static final String NOTIFY_HOST_ATT = "host";
107
108 //doc.xml file elems
109 public static final String DOCXML_SECTION_ELEM = "Section";
110 public static final String DOCXML_DESCRIPTION_ELEM = "Description";
111 public static final String DOCXML_METADATA_ELEM = "Metadata";
112 public static final String DOCXML_CONTENT_ELEM = "Content";
113
114 // elems for the pages to be processed by xslt
115 public final static String PAGE_ELEM = "page";
116 public final static String CONFIGURATION_ELEM = "config";
117 public final static String PAGE_REQUEST_ELEM = "pageRequest";
118 public final static String PAGE_RESPONSE_ELEM = "pageResponse";
119 public final static String PAGE_EXTRA_ELEM = "pageExtra";
120
121 //public final static String DESCRIPTION_ELEM = "description";
122
123 public static final String ACTION_ELEM = "action";
124 public static final String SUBACTION_ELEM = "subaction";
125
126 // add on to another elem type to get a list of that type
127 public static final String LIST_MODIFIER = "List";
128 // used to refer back to another element type
129 public static final String REF_MODIFIER = "Ref";
130 // greenstone xml attributes
131 public static final String COLLECTION_ATT = "collection";
132 public static final String NAME_ATT = "name";
133 public static final String TO_ATT = "to";
134 public static final String USER_ID_ATT = "uid";
135 public static final String FROM_ATT = "from";
136 public static final String LANG_ATT = "lang";
137 public static final String TYPE_ATT = "type";
138 public static final String DB_TYPE_ATT = "dbType";
139 public static final String VALUE_ATT = "value";
140 public static final String DEFAULT_ATT = "default";
141 public static final String INFO_ATT = "info";
142 public static final String ACTION_ATT = "action";
143 public static final String SUBACTION_ATT = "subaction";
144 public static final String OUTPUT_ATT = "output";
145 public static final String ADDRESS_ATT = "address";
146 public static final String LOCAL_SITE_ATT = "localSite";
147 public static final String LOCAL_SITE_NAME_ATT = "localSiteName";
148 public static final String STATUS_ERROR_CODE_ATT = "code";
149 public static final String STATUS_PROCESS_ID_ATT = "pid";
150 public static final String PARAM_SHORTNAME_ATT = "shortname";
151 public static final String PARAM_IGNORE_POS_ATT = "ignore";
152 public static final String CLASSIFIER_CONTENT_ATT = "content";
153 public static final String ERROR_TYPE_ATT = "type";
154 public static final String COLLECT_TYPE_ATT = "ct";
155 public static final String HIDDEN_ATT = "hidden";
156
157 // document stuff
158 public static final String DOC_TYPE_ATT = "docType";
159 public static final String DOC_NODE_ELEM = "documentNode";
160 public static final String NODE_CONTENT_ELEM = "nodeContent";
161 public static final String NODE_STRUCTURE_ELEM = "nodeStructure";
162 public static final String NODE_ID_ATT = "nodeID";
163 public static final String HREF_ID_ATT = "hrefId"; // for ids that need translating
164 public static final String ID_MOD_ATT = "idMod"; // might hold .rt etc for hrefIds
165 public static final String NODE_OID = "oid";
166 public static final String NODE_NAME_ATT = "nodeName";
167 public static final String NODE_TYPE_ATT = "nodeType";
168 public static final String NODE_RANK_ATT = "rank";
169 public static final String NODE_TYPE_ROOT = "root";
170 public static final String NODE_TYPE_INTERNAL = "internal";
171 public static final String NODE_TYPE_LEAF = "leaf";
172
173 public static final String DOC_TYPE_SIMPLE = "simple";
174 public static final String DOC_TYPE_PAGED = "paged";
175 public static final String DOC_TYPE_HIERARCHY = "hierarchy";
176
177 public static final String SESSION_EXPIRATION = "session_expiration";
178 public static final String USER_SESSION_CACHE_ATT = "user_session_cache";
179
180 // classifier stuff
181 public static final String CLASS_NODE_ELEM = "classifierNode";
182 public static final String CLASS_NODE_ORIENTATION_ATT = "orientation";
183
184 // parameter types
185 public static final String PARAM_TYPE_INTEGER = "integer";
186 public static final String PARAM_TYPE_BOOLEAN = "boolean";
187 public static final String PARAM_TYPE_ENUM_START = "enum";
188 public static final String PARAM_TYPE_ENUM_SINGLE = "enum_single";
189 public static final String PARAM_TYPE_ENUM_MULTI = "enum_multi";
190 public static final String PARAM_TYPE_STRING = "string";
191 public static final String PARAM_TYPE_TEXT = "text";
192 public static final String PARAM_TYPE_MULTI = "multi";
193 public static final String PARAM_TYPE_FILE = "file";
194 public static final String PARAM_TYPE_INVISIBLE = "invisible";
195 // stuff for text strings
196 public static final String DISPLAY_TEXT_ELEM = "displayItem";
197 // the following are used for the name attributes
198 public static final String DISPLAY_TEXT_NAME = "name";
199 public static final String DISPLAY_TEXT_SUBMIT = "submit";
200 public static final String DISPLAY_TEXT_DESCRIPTION = "description";
201
202 // request types
203 // get the module description
204 public static final String REQUEST_TYPE_DESCRIBE = "describe";
205 // startup a process
206 public static final String REQUEST_TYPE_PROCESS = "process";
207 // get the status of an ongoing process
208 public static final String REQUEST_TYPE_STATUS = "status";
209 // system type request - eg reload a collection
210 public static final String REQUEST_TYPE_SYSTEM = "system";
211 // page requests to the Receptionist/Actions
212 public static final String REQUEST_TYPE_PAGE = "page"; // used to be cgi
213 // get any format info for a service
214 public static final String REQUEST_TYPE_FORMAT = "format";
215 // modify the requests
216 public static final String REQUEST_TYPE_MESSAGING = "messaging";
217 // save the format string
218 public static final String REQUEST_TYPE_FORMAT_STRING = "formatString";
219 // check credentials
220 public static final String REQUEST_TYPE_SECURITY = "security";
221
222 // service types
223 public static final String SERVICE_TYPE_QUERY = "query";
224 public static final String SERVICE_TYPE_RETRIEVE = "retrieve";
225 public static final String SERVICE_TYPE_BROWSE = "browse";
226 public static final String SERVICE_TYPE_APPLET = "applet";
227 public static final String SERVICE_TYPE_PROCESS = "process";
228 public static final String SERVICE_TYPE_ENRICH = "enrich";
229 public static final String SERVICE_TYPE_OAI = "oai";
230 public static final String FLAX_PAGE = "flaxPage";
231 public static final String FLAX_PAGE_GENERATION = "FlaxPageGeneration";
232
233 // system command types and attributes
234 public static final String SYSTEM_TYPE_CONFIGURE = "configure";
235 public static final String SYSTEM_TYPE_ACTIVATE = "activate";
236 public static final String SYSTEM_TYPE_DEACTIVATE = "deactivate";
237 public static final String SYSTEM_TYPE_PING = "ping";
238 //public static final String SYSTEM_TYPE_ISPERSISTENT = "is-persistent";
239
240 public static final String SYSTEM_SUBSET_ATT = "subset";
241 public static final String SYSTEM_MODULE_TYPE_ATT = "moduleType";
242 public static final String SYSTEM_MODULE_NAME_ATT = "moduleName";
243
244 // communicator types
245 public static final String COMM_TYPE_SOAP_JAVA = "soap";
246
247 // error types
248 public static final String ERROR_TYPE_SYNTAX = "syntax";
249 public static final String ERROR_TYPE_SYSTEM = "system";
250 public static final String ERROR_TYPE_INVALID_ID = "invalid_id";
251 public static final String ERROR_TYPE_OTHER = "other";
252
253 // some system wide param names
254 public static final String SUBSET_PARAM = "subset";
255
256 //for plugin
257 public static final String PLUGIN_ELEM = "plugin";
258 public static final String IMPORT_ELEM = "import";
259
260 //for authentication
261 public static final String AUTHEN_NODE_ELEM = "authenticationNode";
262 public static final String USER_NODE_ELEM = "userNode";
263
264 //for configure action results
265 public static final String SUCCESS = "success";
266 public static final String ERROR = "error";
267
268 //security tags and attributes
269 public static final String SECURITY_ELEM = "security";
270 public static final String SCOPE_ATT = "scope";
271 public static final String DEFAULT_ACCESS_ATT = "default_access";
272 public static final String EXCEPTION_ELEM = "exception";
273 public static final String DOCUMENT_SET_ELEM = "documentSet";
274 public static final String GROUP_ELEM = "group";
275 public static final String MATCH_ELEM = "match";
276 public static final String FIELD_ATT = "field";
277 public static final String USER_INFORMATION_ELEM = "userInformation";
278 public static final String USERNAME_ATT = "username";
279 public static final String GROUPS_ATT = "groups";
280 public static final String BASE_URL = "baseURL";
281
282 /**
283 * takes a list of elements, and returns an array of strings of the values
284 * of attribute att_name
285 */
286 public static String[] getAttributeValuesFromList(Element list, String att_name)
287 {
288
289 NodeList children = list.getChildNodes();
290
291 int num_nodes = children.getLength();
292 String[] ids = new String[num_nodes];
293 for (int i = 0; i < num_nodes; i++)
294 {
295 Element e = (Element) children.item(i);
296 String id = e.getAttribute(att_name);
297 ids[i] = id;
298 }
299
300 return ids;
301 }
302
303 public static HashMap<String, Serializable> extractParams(Element xml, boolean deep)
304 {
305 return extractParams(xml, deep, null);
306 }
307
308 /**
309 * takes a paramList element, and gets a HashMap of name-value pairs if
310 * deep=true, extracts embedded params, otherwise just top level params
311 */
312 public static HashMap<String, Serializable> extractParams(Element xml, boolean deep, String toFind)
313 {
314
315 if (!xml.getNodeName().equals(PARAM_ELEM + LIST_MODIFIER))
316 {
317 logger.error("paramList element should have been passed to extractParams, instead it was " + xml.getNodeName());
318 return null;
319 }
320
321 NodeList params = null;
322 if (deep)
323 { // get all the nested ones
324 params = xml.getElementsByTagName(PARAM_ELEM);
325 }
326 else
327 { // just get the top level ones
328 params = xml.getChildNodes();
329 }
330 HashMap<String, Serializable> param_map = new HashMap<String, Serializable>();
331 for (int i = 0; i < params.getLength(); i++)
332 {
333 if (params.item(i).getNodeName().equals(PARAM_ELEM))
334 {
335 Element param = (Element) params.item(i);
336 String name = param.getAttribute(NAME_ATT);
337 String value = getValue(param); //att or content
338
339 // For only one parameter
340 if (toFind != null && name.equals(toFind))
341 {
342 param_map.put(name, value);
343 return param_map;
344 }
345 else if (toFind != null)
346 continue;
347
348 int pos = name.indexOf('.');
349 if (pos == -1)
350 { // a base param
351 param_map.put(name, value);
352 }
353 else
354 { // a namespaced param
355
356 String namespace = name.substring(0, pos);
357 name = name.substring(pos + 1);
358 HashMap<String, String> map = (HashMap<String, String>) param_map.get(namespace);
359 if (map == null)
360 {
361 map = new HashMap<String, String>();
362 param_map.put(namespace, map);
363 }
364 map.put(name, value);
365 }
366 }
367 }
368 return param_map;
369 }
370
371 /** gets the value att or the text content */
372 public static String getValue(Element e)
373 {
374 String val = e.getAttribute(VALUE_ATT);
375 if (val == null || val.equals(""))
376 {
377 // have to get it out of the text
378 val = getNodeText(e);
379
380 }
381 else
382 {
383 // unescape the xml stuff
384 val = unXmlSafe(val);
385 }
386 return val;
387 }
388
389 /** extracts the text out of a node */
390 public static Node getNodeTextNode(Element param)
391 {
392 param.normalize();
393 Node n = param.getFirstChild();
394 while (n != null && n.getNodeType() != Node.TEXT_NODE)
395 {
396 n = n.getNextSibling();
397 }
398 return n;
399 }
400
401 /** extracts the text out of a node */
402 public static String getNodeText(Element param)
403 {
404 Node text_node = getNodeTextNode(param);
405 if (text_node == null)
406 {
407 return "";
408 }
409 return text_node.getNodeValue();
410 }
411
412 public static void setNodeText(Element elem, String text)
413 {
414 Node old_text_node = getNodeTextNode(elem);
415 if (old_text_node != null)
416 {
417 elem.removeChild(old_text_node);
418 }
419 Text t = elem.getOwnerDocument().createTextNode(text);
420 elem.appendChild(t);
421 }
422
423 /** add text to a document/subsection element */
424 public static boolean addDocText(Document owner, Element doc, String text)
425 {
426
427 Element content = owner.createElement(NODE_CONTENT_ELEM);
428 Text t = owner.createTextNode(text);
429 content.appendChild(t);
430 doc.appendChild(content);
431 return true;
432 }
433
434 /** add an error message, unknown error type */
435 public static boolean addError(Document owner, Element doc, String text)
436 {
437 return addError(owner, doc, text, ERROR_TYPE_OTHER);
438 }
439
440 /** add an error message */
441 public static boolean addError(Document owner, Element doc, String text, String error_type)
442 {
443
444 Element content = owner.createElement(ERROR_ELEM);
445 content.setAttribute(ERROR_TYPE_ATT, error_type);
446 Text t = owner.createTextNode(text);
447 content.appendChild(t);
448 doc.appendChild(content);
449 return true;
450 }
451
452 /** add an error message */
453 public static boolean addError(Document owner, Element doc, Throwable error)
454 {
455 return addError(owner, doc, error, ERROR_TYPE_OTHER);
456 }
457
458 /** add an error message */
459 public static boolean addError(Document owner, Element doc, Throwable error, String error_type)
460 {
461 error.printStackTrace();
462 return addError(owner, doc, error.toString(), error_type);
463 }
464
465 public static Element createMetadataParamList(Document owner, Vector meta_values)
466 {
467
468 Element meta_param_list = owner.createElement(PARAM_ELEM + LIST_MODIFIER);
469 Iterator i = meta_values.iterator();
470 while (i.hasNext())
471 {
472 String next = (String) i.next();
473 Element meta_param = owner.createElement(PARAM_ELEM);
474 meta_param_list.appendChild(meta_param);
475 meta_param.setAttribute(NAME_ATT, "metadata");
476 meta_param.setAttribute(VALUE_ATT, next);
477 }
478 return meta_param_list;
479 }
480
481 /** adds a metadata elem to a list */
482 public static boolean addMetadata(Document owner, Element list, String meta_name, String meta_value)
483 {
484 if (meta_value == null || meta_value.equals(""))
485 {
486 return false;
487 }
488 Element data = owner.createElement(METADATA_ELEM);
489 data.setAttribute(NAME_ATT, meta_name);
490 Text t = owner.createTextNode(meta_value);
491 data.appendChild(t);
492 list.appendChild(data);
493 return true;
494
495 }
496
497 /**
498 * copies the metadata out of the metadataList of 'from' into the
499 * metadataList of 'to'
500 */
501 public static boolean mergeMetadataLists(Node to, Node from)
502 {
503 Node from_meta = getChildByTagName(from, METADATA_ELEM + LIST_MODIFIER);
504 if (from_meta == null)
505 { // nothing to copy
506 return true;
507 }
508 return mergeMetadataFromList(to, from_meta);
509 }
510
511 /**
512 * copies the metadata out of the meta_list metadataList into the
513 * metadataList of 'to'
514 */
515 public static boolean mergeMetadataFromList(Node to, Node meta_list)
516 {
517 if (meta_list == null)
518 return false;
519 Node to_meta = getChildByTagName(to, METADATA_ELEM + LIST_MODIFIER);
520 Document to_owner = to.getOwnerDocument();
521 if (to_meta == null)
522 {
523 to.appendChild(to_owner.importNode(meta_list, true));
524 return true;
525 }
526 // copy individual metadata elements
527 NodeList meta_items = ((Element) meta_list).getElementsByTagName(METADATA_ELEM);
528 for (int i = 0; i < meta_items.getLength(); i++)
529 {
530 to_meta.appendChild(to_owner.importNode(meta_items.item(i), true));
531 }
532 return true;
533 }
534
535 /** copies all the children from from to to */
536 public static boolean mergeElements(Element to, Element from)
537 {
538
539 Document owner = to.getOwnerDocument();
540 Node child = from.getFirstChild();
541 while (child != null)
542 {
543 to.appendChild(owner.importNode(child, true));
544 child = child.getNextSibling();
545 }
546 return true;
547 }
548
549 /** returns the (first) element child of the node n */
550 public static Element getFirstElementChild(Node n)
551 {
552
553 Node child = n.getFirstChild();
554 while (child != null)
555 {
556 if (child.getNodeType() == Node.ELEMENT_NODE)
557 {
558 return (Element) child;
559 }
560 child = child.getNextSibling();
561 }
562 return null; //no element child found
563 }
564
565 /** returns the (first) child element with the given name */
566 public static Node getChildByTagName(Node n, String name)
567 {
568 if (n != null)
569 { // this line is an attempted solution to the NullPointerException mentioned
570 // in trac bug ticket #225. If n is null can't do n.getFirstChild() below. As per bug #225:
571 // GSXML.getNodeByPath() is called by GS2BrowseAction, which then calls this method.
572 // If n is null, null will be returned which GS2BrowseAction already checks for. It's here
573 // that the NullPointerException was thrown.
574
575 Node child = n.getFirstChild();
576 while (child != null)
577 {
578 if (child.getNodeName().equals(name))
579 {
580 return child;
581 }
582 child = child.getNextSibling();
583 }
584 }
585 return null; //not found
586 }
587
588 /**
589 * returns the (nth) child element with the given name index numbers start
590 * at 0
591 */
592 public static Node getChildByTagNameIndexed(Node n, String name, int index)
593 {
594 if (index == -1)
595 {
596 return getChildByTagName(n, name);
597 }
598 int count = 0;
599 Node child = n.getFirstChild();
600 while (child != null)
601 {
602 if (child.getNodeName().equals(name))
603 {
604 if (count == index)
605 {
606 return child;
607 }
608 else
609 {
610 count++;
611 }
612 }
613 child = child.getNextSibling();
614 }
615 return null; //not found
616 }
617
618 /**
619 * takes an xpath type expression of the form name/name/... and returns the
620 * first node that matches, or null if not found
621 */
622 public static Node getNodeByPath(Node n, String path)
623 {
624
625 String link = GSPath.getFirstLink(path);
626 path = GSPath.removeFirstLink(path);
627 while (!link.equals(""))
628 {
629 n = getChildByTagName(n, link);
630 if (n == null)
631 {
632 return null;
633 }
634 link = GSPath.getFirstLink(path);
635 path = GSPath.removeFirstLink(path);
636 }
637 return n;
638 }
639
640 /**
641 * takes an xpath type expression of the form name/name/... and returns the
642 * first node that matches, or null if not found can include [i] indices.
643 * index numbers start at 0
644 */
645 public static Node getNodeByPathIndexed(Node n, String path)
646 {
647
648 String link = GSPath.getFirstLink(path);
649 int index = GSPath.getIndex(link);
650 if (index != -1)
651 {
652 link = GSPath.removeIndex(link);
653 }
654 path = GSPath.removeFirstLink(path);
655 while (!link.equals(""))
656 {
657 n = getChildByTagNameIndexed(n, link, index);
658 if (n == null)
659 {
660 return null;
661 }
662 link = GSPath.getFirstLink(path);
663 index = GSPath.getIndex(link);
664 if (index != -1)
665 {
666 link = GSPath.removeIndex(link);
667 }
668 path = GSPath.removeFirstLink(path);
669 }
670 return n;
671 }
672
673 public static HashMap<String, Node> getChildrenMap(Node n)
674 {
675
676 HashMap<String, Node> map = new HashMap<String, Node>();
677 Node child = n.getFirstChild();
678 while (child != null)
679 {
680 String name = child.getNodeName();
681 map.put(name, child);
682 child = child.getNextSibling();
683 }
684 return map;
685 }
686
687 public static NodeList getChildrenByTagName(Node n, String name)
688 {
689 MyNodeList node_list = new MyNodeList();
690 Node child = n.getFirstChild();
691 while (child != null)
692 {
693 if (child.getNodeName().equals(name))
694 {
695 node_list.addNode(child);
696 }
697 child = child.getNextSibling();
698 }
699 return node_list;
700 }
701
702 /** Duplicates an element, but gives it a new name */
703 public static Element duplicateWithNewName(Document owner, Element element, String element_name, boolean with_attributes)
704 {
705 return duplicateWithNewNameNS(owner, element, element_name, null, with_attributes);
706 }
707
708 /** Duplicates an element, but gives it a new name */
709 public static Element duplicateWithNewNameNS(Document owner, Element element, String element_name, String namespace_uri, boolean with_attributes)
710 {
711 Element duplicate;
712 if (namespace_uri == null)
713 {
714 duplicate = owner.createElement(element_name);
715 }
716 else
717 {
718 duplicate = owner.createElementNS(namespace_uri, element_name);
719 }
720 // Copy element attributes
721 if (with_attributes)
722 {
723 NamedNodeMap attributes = element.getAttributes();
724 for (int i = 0; i < attributes.getLength(); i++)
725 {
726 Node attribute = attributes.item(i);
727 duplicate.setAttribute(attribute.getNodeName(), attribute.getNodeValue());
728 }
729 }
730
731 // Copy element children
732 NodeList children = element.getChildNodes();
733 for (int i = 0; i < children.getLength(); i++)
734 {
735 Node child = children.item(i);
736 duplicate.appendChild(owner.importNode(child, true));
737 }
738
739 return duplicate;
740 }
741
742 public static void copyAllChildren(Element to, Element from)
743 {
744
745 Document to_doc = to.getOwnerDocument();
746 Node child = from.getFirstChild();
747 while (child != null)
748 {
749 to.appendChild(to_doc.importNode(child, true));
750 child = child.getNextSibling();
751 }
752 }
753
754 /** returns a basic request message */
755 public static Element createBasicRequest(Document owner, String request_type, String to, UserContext userContext)
756 {
757 Element request = owner.createElement(REQUEST_ELEM);
758 request.setAttribute(TYPE_ATT, request_type);
759 request.setAttribute(LANG_ATT, userContext._lang);
760 request.setAttribute(TO_ATT, to);
761 request.setAttribute(USER_ID_ATT, userContext._userID);
762 return request;
763 }
764
765 public static Element createBasicResponse(Document owner, String from)
766 {
767 Element response = owner.createElement(GSXML.RESPONSE_ELEM);
768 response.setAttribute(GSXML.FROM_ATT, from);
769 response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
770 return response;
771 }
772
773 public static Element createMetadataElement(Document owner, String name, String value)
774 {
775 Element metaElem = owner.createElement(GSXML.METADATA_ELEM);
776 metaElem.setAttribute(GSXML.NAME_ATT, name);
777 metaElem.setAttribute(GSXML.VALUE_ATT, value);
778 return metaElem;
779 }
780
781 public static Element createTextElement(Document owner, String elem_name, String text)
782 {
783 Element e = owner.createElement(elem_name);
784 Text t = owner.createTextNode(text);
785 e.appendChild(t);
786 return e;
787
788 }
789
790 public static Element createTextElement(Document owner, String elem_name, String text, String att_name, String att_value)
791 {
792 Element e = owner.createElement(elem_name);
793 e.setAttribute(att_name, att_value);
794 Text t = owner.createTextNode(text);
795 e.appendChild(t);
796 return e;
797
798 }
799
800 public static Element createDisplayTextElement(Document owner, String text_name, String text)
801 {
802 Element e = owner.createElement(DISPLAY_TEXT_ELEM);
803 e.setAttribute(NAME_ATT, text_name);
804 Text t = owner.createTextNode(text);
805 e.appendChild(t);
806 return e;
807
808 }
809
810 public static Element createParameter(Document owner, String name, String value)
811 {
812 Element param = owner.createElement(PARAM_ELEM);
813 param.setAttribute(NAME_ATT, name);
814 param.setAttribute(VALUE_ATT, value);
815 return param;
816 }
817
818 public static void addParametersToList(Document owner, Element param_list, HashMap params)
819 {
820 if (params == null)
821 {
822 return;
823 }
824
825 Set items = params.entrySet();
826 Iterator i = items.iterator();
827 while (i.hasNext())
828 {
829 Map.Entry m = (Map.Entry) i.next();
830 param_list.appendChild(createParameter(owner, (String) m.getKey(), (String) m.getValue()));
831 }
832
833 }
834
835 public static Element createParameterDescription(Document owner, String id, String display_name, String type, String default_value, String[] option_ids, String[] option_names)
836 {
837
838 Element p = owner.createElement(PARAM_ELEM);
839 p.setAttribute(NAME_ATT, id);
840 p.setAttribute(TYPE_ATT, type);
841 p.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, display_name));
842
843 if (default_value != null)
844 {
845 p.setAttribute(DEFAULT_ATT, default_value);
846 }
847 if (option_ids != null && option_names != null)
848 {
849 for (int i = 0; i < option_ids.length; i++)
850 {
851 Element e = owner.createElement(PARAM_OPTION_ELEM);
852 e.setAttribute(NAME_ATT, option_ids[i]);
853 e.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, option_names[i]));
854 p.appendChild(e);
855 }
856 }
857 return p;
858 }
859
860 public static Element createParameterDescription2(Document owner, String id, String display_name, String type, String default_value, ArrayList<String> option_ids, ArrayList<String> option_names)
861 {
862
863 Element p = owner.createElement(PARAM_ELEM);
864 p.setAttribute(NAME_ATT, id);
865 p.setAttribute(TYPE_ATT, type);
866 p.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, display_name));
867 if (default_value != null)
868 {
869 p.setAttribute(DEFAULT_ATT, default_value);
870 }
871 if (option_ids != null && option_names != null)
872 {
873 for (int i = 0; i < option_ids.size(); i++)
874 {
875 Element e = owner.createElement(PARAM_OPTION_ELEM);
876 e.setAttribute(NAME_ATT, option_ids.get(i));
877 e.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, option_names.get(i)));
878 p.appendChild(e);
879 }
880 }
881 return p;
882 }
883
884 /** returns the element parent/node_name[@attribute_name='attribute_value'] */
885 public static Element getNamedElement(Element parent, String node_name, String attribute_name, String attribute_value)
886 {
887
888 NodeList children = parent.getChildNodes();
889 for (int i = 0; i < children.getLength(); i++)
890 {
891 Node child = children.item(i);
892 if (child.getNodeName().equals(node_name))
893 {
894 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
895 return (Element) child;
896 }
897 }
898 // not found
899 return null;
900 }
901
902 /**
903 * returns a NodeList of elements:
904 * ancestor/node_name[@attribute_name='attribute_value']
905 */
906 public static NodeList getNamedElements(Element ancestor, String node_name, String attribute_name, String attribute_value)
907 {
908 MyNodeList node_list = new MyNodeList();
909 NodeList children = ancestor.getElementsByTagName(node_name);
910
911 if (children != null && children.getLength() > 0)
912 {
913
914 for (int i = 0; i < children.getLength(); i++)
915 {
916 Node child = children.item(i);
917 if (child.getNodeName().equals(node_name))
918 {
919 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
920 node_list.addNode(child);
921 }
922 }
923 }
924 return node_list;
925 }
926
927 public static int SORT_TYPE_STRING = 0;
928 public static int SORT_TYPE_INT = 1;
929 public static int SORT_TYPE_FLOAT = 2;
930
931 // sort type:
932 public static Element insertIntoOrderedList(Element parent_node, String node_name, Element start_from_elem, Element new_elem, String sort_att, boolean descending)
933 {
934 if (new_elem == null)
935 return null;
936 Element cloned_elem = (Element) parent_node.getOwnerDocument().importNode(new_elem, true);
937 if (start_from_elem == null)
938 {
939 parent_node.appendChild(cloned_elem);
940 return cloned_elem;
941 }
942
943 Node current_node = start_from_elem;
944 String insert_att = cloned_elem.getAttribute(sort_att);
945 String list_att = start_from_elem.getAttribute(sort_att);
946 while ((!descending && list_att.compareTo(insert_att) < 0) || (descending && list_att.compareTo(insert_att) > 0))
947 {
948 current_node = current_node.getNextSibling();
949 if (current_node == null)
950 break; // end of the list
951 if (!current_node.getNodeName().equals(node_name))
952 {
953 continue; // not a valid node
954 }
955 list_att = ((Element) current_node).getAttribute(sort_att);
956 }
957
958 parent_node.insertBefore(cloned_elem, current_node);
959 return cloned_elem;
960 }
961
962 /**
963 * Returns the appropriate language element from a display elem, display is
964 * the containing element, name is the name of the element to look for, lang
965 * is the preferred language, lang_default is the fall back lang if neither
966 * lang is found, will return the first one it finds
967 */
968 public static String getDisplayText(Element display, String name, String lang, String lang_default)
969 {
970
971 String def = null;
972 String first = null;
973 NodeList elems = display.getElementsByTagName(DISPLAY_TEXT_ELEM);
974 if (elems.getLength() == 0)
975 return "";
976 for (int i = 0; i < elems.getLength(); i++)
977 {
978 Element e = (Element) elems.item(i);
979 String n = e.getAttribute(NAME_ATT);
980 if (name.equals(n))
981 {
982 String l = e.getAttribute(LANG_ATT);
983 if (lang.equals(l))
984 {
985 return getNodeText(e);
986 }
987 else if (lang_default.equals(l))
988 {
989 def = getNodeText(e);
990 }
991 else if (first == null)
992 {
993 first = getNodeText(e);
994 }
995 }
996 else
997 {
998 continue;
999 }
1000 }
1001
1002 if (def != null)
1003 {
1004 return def;
1005 }
1006 if (first != null)
1007 {
1008 return first;
1009 }
1010 return "";
1011 }
1012
1013 // replaces < > " ' & in the original with their entities
1014 public static String xmlSafe(String original)
1015 {
1016
1017 StringBuffer filtered = new StringBuffer(original.length());
1018 char c;
1019 for (int i = 0; i < original.length(); i++)
1020 {
1021 c = original.charAt(i);
1022 if (c == '>')
1023 {
1024 filtered.append("&gt;");
1025 }
1026 else if (c == '<')
1027 {
1028 filtered.append("&lt;");
1029 }
1030 else if (c == '"')
1031 {
1032 filtered.append("&quot;");
1033 }
1034 else if (c == '&')
1035 {
1036 filtered.append("&amp;");
1037 }
1038 else if (c == '\'')
1039 {
1040 filtered.append("&apos;");
1041 }
1042 else
1043 {
1044 filtered.append(c);
1045 }
1046 }
1047 return filtered.toString();
1048 }
1049
1050 // replaces < > " ' & entities with their originals
1051 public static String unXmlSafe(String original)
1052 {
1053
1054 StringBuffer filtered = new StringBuffer(original.length());
1055 char c;
1056 for (int i = 0; i < original.length(); i++)
1057 {
1058 c = original.charAt(i);
1059 if (c == '&')
1060 {
1061 int pos = original.indexOf(";", i);
1062 String entity = original.substring(i + 1, pos);
1063 if (entity.equals("gt"))
1064 {
1065 filtered.append(">");
1066 }
1067 else if (entity.equals("lt"))
1068 {
1069 filtered.append("<");
1070 }
1071 else if (entity.equals("apos"))
1072 {
1073 filtered.append("'");
1074 }
1075 else if (entity.equals("amp"))
1076 {
1077 filtered.append("&");
1078 }
1079 else if (entity.equals("quot"))
1080 {
1081 filtered.append("\"");
1082 }
1083 else
1084 {
1085 filtered.append("&" + entity + ";");
1086 }
1087 i = pos;
1088 }
1089 else
1090 {
1091 filtered.append(c);
1092 }
1093 }
1094 return filtered.toString();
1095 }
1096
1097 public static void printXMLNode(Node e, boolean printText)
1098 {
1099 printXMLNode(e, 0, printText);
1100 }
1101
1102 public static String xmlNodeToString(Node e)
1103 {
1104 StringBuffer sb = new StringBuffer("");
1105 xmlNodeToString(sb, e, true, "\t", 0);
1106 return sb.toString();
1107 }
1108
1109 public static void xmlNodeToString(StringBuffer sb, Node e, boolean indent, String indentString, int depth)
1110 {
1111 if (e.getNodeType() == Node.TEXT_NODE)
1112 {
1113 if (e.getNodeValue() != "")
1114 {
1115 String text = e.getNodeValue();
1116 text = text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("^[\\n\\r\\t\\s]*", "").replaceAll("[\\n\\r\\t\\s]*$", "");
1117 sb.append(text);
1118 }
1119 return;
1120 }
1121
1122 if (e.getNodeType() == Node.COMMENT_NODE)
1123 {
1124 if (e.getNodeValue() != "")
1125 {
1126 sb.append("<!--" + e.getNodeValue() + "-->");
1127 }
1128 return;
1129 }
1130
1131 if (indent)
1132 {
1133 for (int i = 0; i < depth; i++)
1134 {
1135 sb.append(indentString);
1136 }
1137 }
1138
1139 sb.append('<');
1140 sb.append(e.getNodeName());
1141 NamedNodeMap attrs = e.getAttributes();
1142 if (attrs != null)
1143 {
1144 for (int i = 0; i < attrs.getLength(); i++)
1145 {
1146 Node attr = attrs.item(i);
1147 sb.append(' ');
1148 sb.append(attr.getNodeName());
1149 sb.append("=\"");
1150 sb.append(attr.getNodeValue().replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"));
1151 sb.append('"');
1152 }
1153 }
1154 NodeList children = e.getChildNodes();
1155
1156 boolean hasElements = false;
1157 boolean indentSwapped = false;
1158 for (int i = 0; i < children.getLength(); i++)
1159 {
1160 if (children.item(i).getNodeType() == Node.ELEMENT_NODE)
1161 {
1162 hasElements = true;
1163 }
1164 if (children.item(i).getNodeType() == Node.TEXT_NODE && indent)
1165 {
1166 if (children.item(i).getNodeValue().trim().length() > 0)
1167 {
1168 indentSwapped = true;
1169 indent = false;
1170 }
1171 }
1172 }
1173
1174 if (children == null || children.getLength() == 0)
1175 {
1176 sb.append("/>");
1177
1178 if (indent)
1179 {
1180 sb.append("\n");
1181 }
1182 }
1183 else
1184 {
1185 sb.append(">");
1186 if (hasElements && indent)
1187 {
1188 sb.append("\n");
1189 }
1190
1191 int len = children.getLength();
1192 for (int i = 0; i < len; i++)
1193 {
1194 xmlNodeToString(sb, children.item(i), indent, indentString, depth + 1);
1195 }
1196
1197 if (indent)
1198 {
1199 for (int i = 0; i < depth; i++)
1200 {
1201 sb.append(indentString);
1202 }
1203 }
1204
1205 sb.append("</" + e.getNodeName() + ">");
1206
1207 if ((hasElements && indent) || indentSwapped)
1208 {
1209 sb.append("\n");
1210 }
1211 }
1212 }
1213
1214 public static void printXMLNode(Node e, int depth, boolean printText)
1215 { //recursive method call using DOM API...
1216
1217 if (e == null)
1218 {
1219 return;
1220 }
1221
1222 for (int i = 0; i < depth; i++)
1223 System.out.print(' ');
1224
1225 if (e.getNodeType() == Node.TEXT_NODE)
1226 {
1227 if (printText)
1228 {
1229 System.out.println(e.getNodeValue());
1230 }
1231 else
1232 {
1233 System.out.println("text");
1234 }
1235 return;
1236 }
1237
1238 System.out.print('<');
1239 System.out.print(e.getNodeName());
1240 NamedNodeMap attrs = e.getAttributes();
1241
1242 if (attrs != null)
1243 {
1244 for (int i = 0; i < attrs.getLength(); i++)
1245 {
1246 Node attr = attrs.item(i);
1247 System.out.print(' ');
1248 System.out.print(attr.getNodeName());
1249 System.out.print("=\"");
1250 System.out.print(attr.getNodeValue());
1251 System.out.print('"');
1252 }
1253 }
1254
1255 NodeList children = e.getChildNodes();
1256
1257 if (children == null || children.getLength() == 0)
1258 System.out.println("/>");
1259 else
1260 {
1261
1262 System.out.println('>');
1263
1264 int len = children.getLength();
1265 for (int i = 0; i < len; i++)
1266 {
1267 printXMLNode(children.item(i), depth + 1, printText);
1268 }
1269
1270 for (int i = 0; i < depth; i++)
1271 System.out.print(' ');
1272
1273 System.out.println("</" + e.getNodeName() + ">");
1274 }
1275 }
1276
1277 public static void elementToLogAsString(Element e, boolean indent)
1278 {
1279 String str = elementToString(e, indent);
1280 System.err.println(str);
1281 logger.error(str);
1282 }
1283
1284 public static String elementToString(Element e, boolean indent)
1285 {
1286 String str = "";
1287 try
1288 {
1289 TransformerFactory tf = TransformerFactory.newInstance();
1290 Transformer trans = tf.newTransformer();
1291 StringWriter sw = new StringWriter();
1292 if (indent)
1293 {
1294 trans.setOutputProperty(OutputKeys.INDENT, "yes");
1295 }
1296 else
1297 {
1298 trans.setOutputProperty(OutputKeys.INDENT, "no");
1299 }
1300 trans.transform(new DOMSource(e), new StreamResult(sw));
1301 str += sw.toString();
1302 }
1303 catch (Exception ex)
1304 {
1305 str += "Exception: couldn't write " + e + " to log";
1306 }
1307 finally
1308 {
1309 return str;
1310 }
1311 }
1312
1313 public static ArrayList<String> getGroupsFromSecurityResponse(Element securityResponse)
1314 {
1315 ArrayList<String> groups = new ArrayList<String>();
1316
1317 Element groupList = (Element) GSXML.getChildByTagName(securityResponse, GSXML.GROUP_ELEM + GSXML.LIST_MODIFIER);
1318 if (groupList == null)
1319 {
1320 return groups;
1321 }
1322
1323 NodeList groupElems = GSXML.getChildrenByTagName(groupList, GSXML.GROUP_ELEM);
1324
1325 for (int i = 0; i < groupElems.getLength(); i++)
1326 {
1327 Element groupElem = (Element) groupElems.item(i);
1328 groups.add(groupElem.getAttribute(GSXML.NAME_ATT));
1329 }
1330
1331 return groups;
1332 }
1333
1334 public static NodeList getHTMLStructureElements(Document doc)
1335 {
1336 MyNodeList elems = new MyNodeList();
1337
1338 String[] structureTagNames = new String[] { "html", "div", "td", "li" };
1339
1340 for (String tagName : structureTagNames)
1341 {
1342 NodeList htmlElems = doc.getElementsByTagName(tagName);
1343 elems.addNodeList(htmlElems);
1344 }
1345
1346 return elems;
1347 }
1348
1349 public static void addDebugSpanTags(Document doc)
1350 {
1351 NodeList allElements = doc.getElementsByTagName("*");
1352
1353 for (int i = 0; i < allElements.getLength(); i++)
1354 {
1355 Element current = (Element) allElements.item(i);
1356 String debugString = null;
1357 if ((debugString = (String) current.getUserData("GSDEBUGFILENAME")) != null)
1358 {
1359 System.err.println("DEBUGSTRING = " + debugString);
1360
1361 Element xmlSpan = doc.createElement("span");
1362 xmlSpan.setAttribute("style", "display:none;");
1363 xmlSpan.setAttribute("class", "debugSpan");
1364 xmlSpan.appendChild(doc.createTextNode("\"filename\":\"" + debugString + "\", \"xml\":\"" + GSXML.xmlNodeToString((Element) current.getUserData("GSDEBUGXML")) + "\""));
1365
1366 if (current.hasChildNodes())
1367 {
1368 current.insertBefore(xmlSpan, current.getFirstChild());
1369 }
1370 else
1371 {
1372 current.appendChild(xmlSpan);
1373 }
1374 }
1375 }
1376 }
1377}
Note: See TracBrowser for help on using the repository browser.