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

Last change on this file since 37177 was 37177, checked in by davidb, 15 months ago

Introduction of new optional parameter docVersion. If null (or equal to the empty string), then code works as before. Designed to work with the file-level document-version history mechanism, if non-empty, then this value is used to change where doc.xml on the file system is read from

  • Property svn:keywords set to Author Date Id Revision
File size: 53.5 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 java.io.Serializable;
22import java.io.StringWriter;
23import java.util.ArrayList;
24import java.util.HashMap;
25import java.util.Iterator;
26import java.util.Map;
27import java.util.Set;
28import java.util.Vector;
29
30import javax.xml.transform.OutputKeys;
31import javax.xml.transform.Transformer;
32import javax.xml.transform.TransformerFactory;
33import javax.xml.transform.dom.DOMSource;
34import javax.xml.transform.stream.StreamResult;
35
36import org.apache.log4j.Logger;
37import org.w3c.dom.Attr;
38import org.w3c.dom.Document;
39import org.w3c.dom.Element;
40import org.w3c.dom.NamedNodeMap;
41import org.w3c.dom.Node;
42import org.w3c.dom.NodeList;
43import org.w3c.dom.Text;
44
45import org.greenstone.gsdl3.util.MyNodeList;
46import org.greenstone.util.Misc;
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 LIBRARY_PARAM_ELEM = "libraryParam";
65 public static final String CONTENT_ELEM = "content";
66 public static final String RESOURCE_ELEM = "resource";
67 public static final String DOCUMENT_ELEM = "document";
68 public static final String METADATA_ELEM = "metadata";
69 public static final String SERVICE_CLASS_ELEM = "serviceRack";
70 public static final String CLASSIFIER_ELEM = "classifier";
71 public static final String APPLET_ELEM = "applet";
72 public static final String APPLET_DATA_ELEM = "appletData";
73 public static final String CONFIGURE_ELEM = "configure";
74 public static final String STATUS_ELEM = "status";
75 public static final String ERROR_ELEM = "error";
76 public static final String DEFAULT_ELEM = "default";
77 public static final String STYLESHEET_ELEM = "format";//"stylesheet"; // any additional stylesheet stuff is carried in the message inside this elem
78 public static final String FORMAT_ELEM = "format"; // config files use format - should we use this instead of stylesheet??
79 public static final String GLOBAL_FORMAT_ELEM = "globalFormat";
80 public static final String TERM_ELEM = "term";
81 public static final String STOPWORD_ELEM = "stopword";
82 public static final String FACET_ELEM = "facet";
83 public static final String COUNT_ELEM = "count";
84 public static final String SYSTEM_ELEM = "system";
85 public static final String FORMAT_STRING_ELEM = "formatString";
86 public static final String EXTRA_METADATA = "extraMetadata";
87 public static final String PATH_ELEM = "path";
88
89 //config file elems
90 public static final String COLLECTION_CONFIG_ELEM = "collectionConfig";
91 public static final String COLLECTION_BUILD_ELEM = "buildConfig";
92 public static final String COLLECTION_INIT_ELEM = "collectionInit";
93 public static final String RECOGNISE_ELEM = "recognise";
94 public static final String DOC_TYPE_ELEM = "docType";
95 public static final String SEARCH_ELEM = "search";
96 public static final String INFODB_ELEM = "infodb";
97 public static final String INDEX_ELEM = "index";
98 public static final String INDEX_STEM_ELEM = "indexStem";
99 public static final String INDEX_OPTION_ELEM = "indexOption";
100 public static final String PARAM_DEFAULT_ELEM = "paramDefault";
101 public static final String BROWSE_ELEM = "browse";
102 public static final String DISPLAY_ELEM = "display";
103 public static final String LEVEL_ELEM = "level";
104 public static final String REPLACE_ELEM = "replace";
105 public static final String EXTRA_INFO_ELEM = "extraInfo";
106 public static final String DBINFO_ELEM = "dbInfo";
107 public static final String DBNAME_ATT = "dbname";
108 public static final String DBPATH_ATT = "dbpath";
109 public static final String SQLSTATE_ATT = "sqlstate";
110 public static final String DATABASE_TYPE_ELEM = "databaseType";
111 public static final String SHORTNAME_ATT = "shortname";
112 public static final String NOTIFY_ELEM = "notify";
113 public static final String NOTIFY_HOST_ATT = "host";
114
115 //doc.xml file elems
116 public static final String DOCXML_SECTION_ELEM = "Section";
117 public static final String DOCXML_DESCRIPTION_ELEM = "Description";
118 public static final String DOCXML_METADATA_ELEM = "Metadata";
119 public static final String DOCXML_CONTENT_ELEM = "Content";
120
121 // elems for the pages to be processed by xslt
122 public final static String PAGE_ELEM = "page";
123 public final static String CONFIGURATION_ELEM = "config";
124 public final static String PAGE_REQUEST_ELEM = "pageRequest";
125 public final static String PAGE_RESPONSE_ELEM = "pageResponse";
126 public final static String PAGE_EXTRA_ELEM = "pageExtra";
127
128 //public final static String DESCRIPTION_ELEM = "description";
129
130 public static final String ACTION_ELEM = "action";
131 public static final String SUBACTION_ELEM = "subaction";
132
133 // add on to another elem type to get a list of that type
134 public static final String LIST_MODIFIER = "List";
135 // used to refer back to another element type
136 public static final String REF_MODIFIER = "Ref";
137 // greenstone xml attributes
138 public static final String COLLECTION_ATT = "collection";
139 public static final String NAME_ATT = "name";
140 public static final String MATCH_ATT = "match";
141 public static final String TO_ATT = "to";
142 public static final String USER_ID_ATT = "uid";
143 public static final String FROM_ATT = "from";
144 public static final String LANG_ATT = "lang";
145 public static final String KEY_ATT = "key";
146 public static final String DICTIONARY_ATT = "dictionary";
147 public static final String HREF_ATT = "href";
148 public static final String TYPE_ATT = "type";
149 public static final String DB_TYPE_ATT = "dbType";
150 public static final String VALUE_ATT = "value";
151 public static final String DEFAULT_ATT = "default";
152 public static final String INFO_ATT = "info";
153 public static final String ACTION_ATT = "action";
154 public static final String SUBACTION_ATT = "subaction";
155 public static final String OUTPUT_ATT = "output";
156 public static final String ADDRESS_ATT = "address";
157 public static final String LOCAL_SITE_ATT = "localSite";
158 public static final String LOCAL_SITE_NAME_ATT = "localSiteName";
159 public static final String STATUS_ERROR_CODE_ATT = "code";
160 public static final String STATUS_PROCESS_ID_ATT = "pid";
161 public static final String PARAM_SHORTNAME_ATT = "shortname";
162 public static final String PARAM_IGNORE_POS_ATT = "ignore";
163 public static final String CLASSIFIER_CONTENT_ATT = "content";
164 public static final String ERROR_TYPE_ATT = "type";
165 public static final String COLLECT_TYPE_ATT = "ct";
166 public static final String HIDDEN_ATT = "hidden";
167 public static final String FACET_ATT = "facet";
168 public static final String PATH_ATT = "path";
169 public static final String SENSITIVE_ATT = "sensitive";
170 public static final String NO_ARCHIVES_ATT = "no_archives";
171 // document stuff
172 public static final String DOC_TYPE_ATT = "docType";
173 public static final String DOC_VERSION_ATT = "docVersion"; // File-Level Document-Version History _fldv_history
174 public static final String DOC_NODE_ELEM = "documentNode";
175 public static final String NODE_CONTENT_ELEM = "nodeContent";
176 public static final String NODE_STRUCTURE_ELEM = "nodeStructure";
177 public static final String NODE_ID_ATT = "nodeID";
178 public static final String HREF_ID_ATT = "hrefId"; // for ids that need translating
179 public static final String HL_SNIPPET_ELEM = "highlightSnippet";
180 public static final String ID_MOD_ATT = "idMod"; // might hold .rt etc for hrefIds
181 public static final String NODE_OID = "oid";
182 public static final String NODE_NAME_ATT = "nodeName";
183 public static final String NODE_TYPE_ATT = "nodeType";
184 public static final String NODE_RANK_ATT = "rank";
185 public static final String NODE_TYPE_ROOT = "root";
186 public static final String NODE_TYPE_INTERNAL = "internal";
187 public static final String NODE_TYPE_LEAF = "leaf";
188
189 public static final String DOC_TYPE_SIMPLE = "simple";
190 public static final String DOC_TYPE_PAGED = "paged";
191 public static final String DOC_TYPE_HIERARCHY = "hierarchy";
192 public static final String DOC_TYPE_PAGED_HIERARCHY = "pagedhierarchy";
193
194 public static final String SESSION_EXPIRATION = "session_expiration";
195
196 // classifier stuff
197 public static final String CLASS_NODE_ELEM = "classifierNode";
198 public static final String CLASS_NODE_ORIENTATION_ATT = "orientation";
199
200 // parameter types
201 public static final String PARAM_TYPE_INTEGER = "integer";
202 public static final String PARAM_TYPE_BOOLEAN = "boolean";
203 public static final String PARAM_TYPE_ENUM_START = "enum";
204 public static final String PARAM_TYPE_ENUM_SINGLE = "enum_single";
205 public static final String PARAM_TYPE_ENUM_MULTI = "enum_multi";
206 public static final String PARAM_TYPE_STRING = "string";
207 public static final String PARAM_TYPE_TEXT = "text";
208 public static final String PARAM_TYPE_MULTI = "multi";
209 public static final String PARAM_TYPE_FILE = "file";
210 public static final String PARAM_TYPE_INVISIBLE = "invisible";
211 public static final String PARAM_TYPE_CHECKBOX_LIST = "checkbox_list";
212 // stuff for text strings
213 public static final String DISPLAY_TEXT_ELEM = "displayItem";
214 // the following are used for the name attributes
215 public static final String DISPLAY_TEXT_NAME = "name";
216 public static final String DISPLAY_TEXT_SUBMIT = "submit";
217 public static final String DISPLAY_TEXT_DESCRIPTION = "description";
218
219 // request types
220 // get the module description
221 public static final String REQUEST_TYPE_DESCRIBE = "describe";
222 // startup a process
223 public static final String REQUEST_TYPE_PROCESS = "process";
224 // get the status of an ongoing process
225 public static final String REQUEST_TYPE_STATUS = "status";
226 // system type request - eg reload a collection
227 public static final String REQUEST_TYPE_SYSTEM = "system";
228 // page requests to the Receptionist/Actions
229 public static final String REQUEST_TYPE_PAGE = "page"; // used to be cgi
230 // get any format info for a service
231 public static final String REQUEST_TYPE_FORMAT = "format";
232 // modify the requests
233 public static final String REQUEST_TYPE_MESSAGING = "messaging";
234 // save the format string
235 public static final String REQUEST_TYPE_FORMAT_STRING = "formatString";
236 // check credentials
237 public static final String REQUEST_TYPE_SECURITY = "security";
238
239 // service types
240 public static final String SERVICE_TYPE_QUERY = "query";
241 public static final String SERVICE_TYPE_RETRIEVE = "retrieve";
242 public static final String SERVICE_TYPE_BROWSE = "browse";
243 public static final String SERVICE_TYPE_GROUPINFO = "groupinfo";
244 public static final String SERVICE_TYPE_APPLET = "applet";
245 public static final String SERVICE_TYPE_PROCESS = "process";
246 public static final String SERVICE_TYPE_ENRICH = "enrich";
247 public static final String SERVICE_TYPE_OAI = "oai";
248 public static final String FLAX_PAGE = "flaxPage";
249 public static final String FLAX_PAGE_GENERATION = "FlaxPageGeneration";
250
251 // system command types and attributes
252 public static final String SYSTEM_TYPE_CONFIGURE = "configure";
253 public static final String SYSTEM_TYPE_ACTIVATE = "activate";
254 public static final String SYSTEM_TYPE_DEACTIVATE = "deactivate";
255 public static final String SYSTEM_TYPE_PING = "ping";
256 public static final String SYSTEM_TYPE_AUTHENTICATED_PING = "authenticated-ping";
257 //public static final String SYSTEM_TYPE_ISPERSISTENT = "is-persistent";
258
259 public static final String SYSTEM_SUBSET_ATT = "subset";
260 public static final String SYSTEM_MODULE_TYPE_ATT = "moduleType";
261 public static final String SYSTEM_MODULE_NAME_ATT = "moduleName";
262
263 // communicator types
264 public static final String COMM_TYPE_SOAP_JAVA = "soap";
265
266 // error types
267 public static final String ERROR_TYPE_SYNTAX = "syntax";
268 public static final String ERROR_TYPE_SYSTEM = "system";
269 public static final String ERROR_TYPE_INVALID_ID = "invalid_id";
270 public static final String ERROR_TYPE_OTHER = "other";
271
272 // some system wide param names
273 public static final String SUBSET_PARAM = "subset";
274
275 //for plugin
276 public static final String PLUGIN_ELEM = "plugin";
277 public static final String IMPORT_ELEM = "import";
278
279 //for authentication
280 public static final String AUTHEN_NODE_ELEM = "authenticationNode";
281 public static final String USER_NODE_ELEM = "userNode";
282
283 //for configure action results
284 public static final String SUCCESS = "success";
285 public static final String ERROR = "error";
286
287 //security tags and attributes
288 public static final String SECURITY_ELEM = "security";
289 public static final String DISABLED_ATT = "disabled";
290 public static final String SCOPE_ATT = "scope";
291 public static final String SCOPE_COLLECTION = "collection";
292 public static final String SCOPE_DOCUMENT = "document";
293 public static final String DEFAULT_ACCESS_ATT = "default_access";
294 public static final String ACCESS_PUBLIC = "public";
295 public static final String ACCESS_PRIVATE = "private";
296 public static final String VERIFY_ATT = "humanVerify";
297 public static final String SITE_KEY_ATT = "siteKey";
298 public static final String SECRET_KEY_ATT = "secretKey";
299 public static final String USE_RECAPTCHA_ATT = "useRecaptcha";
300 public static final String EXCEPTION_ELEM = "exception";
301 public static final String DOCUMENT_SET_ELEM = "documentSet";
302 public static final String GROUP_ELEM = "group";
303 public static final String MATCH_ELEM = "match";
304 public static final String FIELD_ATT = "field";
305 public static final String USER_INFORMATION_ELEM = "userInformation";
306 public static final String USERNAME_ATT = "username";
307 public static final String GROUPS_ATT = "groups";
308 public static final String EDIT_ENABLED_ATT = "editEnabled";
309 public static final String BASE_URL = "baseURL";
310
311 // only for authenticated-ping
312 public static final String PASSWORD_ATT = "password";
313
314 //for classifiers
315 public static final String CHILD_TYPE_ATT = "childType";
316 public static final String CLASSIFIER_STYLE_ATT = "classifierStyle";
317 public static final String HLIST = "HList";
318 public static final String VLIST = "VList";
319
320 //for namespaces
321 public static final String XSL_NAMESPACE = "http://www.w3.org/1999/XSL/Transform";
322 public static final String GSF_NAMESPACE = "http://www.greenstone.org/greenstone3/schema/ConfigFormat";
323 public static final String GSLIB_NAMESPACE = "http://www.greenstone.org/skinning";
324 public static final String JAVA_NAMESPACE = "http://xml.apache.org/xslt/java";
325 public static final String UTIL_NAMESPACE = "xalan://org.greenstone.gsdl3.util.XSLTUtil";
326
327 // all the namespaces in a string for easy addition to a string
328 public static final String ALL_NAMESPACES_ATTS = "xmlns:gsf='" + GSF_NAMESPACE + "' xmlns:xsl='" + XSL_NAMESPACE + "' xmlns:gslib='" + GSLIB_NAMESPACE + "' xmlns:java='" + JAVA_NAMESPACE + "' xmlns:util='" + UTIL_NAMESPACE +"' ";
329 public static final String STD_NAMESPACES_ATTS = "xmlns:gsf='" + GSF_NAMESPACE + "' xmlns:xsl='" + XSL_NAMESPACE + "' xmlns:gslib='" + GSLIB_NAMESPACE +"' ";
330
331 //Groups configuration
332 public static final String HIERARCHY_ELEM = "hierarchy";
333 public static final String GROUP_DESC_ELEM = "groupDescriptions";
334 public static final String TITLE_ELEM = "title";
335 public static final String DESCRIPTION_ELEM = "description";
336 public static final String SHORT_DESCRIPTION_ELEM = "shortDescription";
337 public static final String BACKGROUND_IMAGE_ELEM = "backgroundImage";
338 public static final String POSITION_ATT = "position";
339
340 /**
341 * takes a list of elements, and returns an array of strings of the values
342 * of attribute att_name
343 */
344 public static String[] getAttributeValuesFromList(Element list, String att_name)
345 {
346
347 NodeList children = list.getChildNodes();
348
349 int num_nodes = children.getLength();
350 String[] ids = new String[num_nodes];
351 for (int i = 0; i < num_nodes; i++)
352 {
353 Element e = (Element) children.item(i);
354 String id = e.getAttribute(att_name);
355 ids[i] = id;
356 }
357
358 return ids;
359 }
360
361 public static HashMap<String, String> getParamMap(NodeList params) {
362 HashMap<String, String> map = new HashMap<String, String>();
363 for(int i=0; i<params.getLength(); i++) {
364 Element param = (Element)params.item(i);
365 String param_name = param.getAttribute(NAME_ATT);
366 String param_value = param.getAttribute(VALUE_ATT);
367 map.put(param_name, param_value);
368 }
369 return map;
370 }
371
372 public static HashMap<String, Serializable> extractParams(Element xml, boolean deep)
373 {
374 return extractParams(xml, deep, null);
375 }
376
377 /**
378 * takes a paramList element, and gets a HashMap of name-value pairs if
379 * deep=true, extracts embedded params, otherwise just top level params
380 */
381 public static HashMap<String, Serializable> extractParams(Element xml, boolean deep, String toFind)
382 {
383 if (xml == null)
384 {
385 return null;
386 }
387
388 if (!xml.getNodeName().equals(PARAM_ELEM + LIST_MODIFIER))
389 {
390 logger.error("paramList element should have been passed to extractParams, instead it was " + xml.getNodeName());
391 return null;
392 }
393
394 NodeList params = null;
395 if (deep)
396 { // get all the nested ones
397 params = xml.getElementsByTagName(PARAM_ELEM);
398 }
399 else
400 { // just get the top level ones
401 params = xml.getChildNodes();
402 }
403 HashMap<String, Serializable> param_map = new HashMap<String, Serializable>();
404 for (int i = 0; i < params.getLength(); i++)
405 {
406 if (params.item(i).getNodeName().equals(PARAM_ELEM))
407 {
408 Element param = (Element) params.item(i);
409 String name = param.getAttribute(NAME_ATT);
410 String value = getValue(param); //att or content
411
412 // For only one parameter
413 if (toFind != null && name.equals(toFind))
414 {
415 param_map.put(name, value);
416 return param_map;
417 }
418 else if (toFind != null)
419 continue;
420
421 int pos = name.indexOf('.');
422 if (pos == -1)
423 { // a base param
424 param_map.put(name, value);
425 }
426 else
427 { // a namespaced param
428
429 String namespace = name.substring(0, pos);
430 name = name.substring(pos + 1);
431 HashMap<String, String> map = (HashMap<String, String>) param_map.get(namespace);
432 if (map == null)
433 {
434 map = new HashMap<String, String>();
435 param_map.put(namespace, map);
436 }
437 map.put(name, value);
438 }
439 }
440 }
441 return param_map;
442 }
443
444 /** gets the value att or the text content */
445 public static String getValue(Element e)
446 {
447 String val = e.getAttribute(VALUE_ATT);
448 if (val == null || val.equals(""))
449 {
450 // have to get it out of the text
451 val = getNodeText(e);
452
453 }
454 else
455 {
456 // unescape the xml stuff
457 val = unXmlSafe(val);
458 }
459 return val;
460 }
461
462 /** extracts the text out of a node */
463 public static Node getNodeTextNode(Element param)
464 {
465 param.normalize();
466 Node n = param.getFirstChild();
467 while (n != null && n.getNodeType() != Node.TEXT_NODE)
468 {
469 n = n.getNextSibling();
470 }
471 return n;
472 }
473
474 /** extracts the text out of a node */
475 public static String getNodeText(Element param)
476 {
477 Node text_node = getNodeTextNode(param);
478 if (text_node == null)
479 {
480 return "";
481 }
482 return text_node.getNodeValue();
483 }
484
485 public static void setNodeText(Element elem, String text)
486 {
487 Node old_text_node = getNodeTextNode(elem);
488 if (old_text_node != null)
489 {
490 elem.removeChild(old_text_node);
491 }
492 Text t = elem.getOwnerDocument().createTextNode(text);
493 elem.appendChild(t);
494 }
495
496 /** add text to a document/subsection element */
497 public static boolean addDocText(Element doc, String text)
498 {
499
500 Element content = doc.getOwnerDocument().createElement(NODE_CONTENT_ELEM);
501 Text t = doc.getOwnerDocument().createTextNode(text);
502 content.appendChild(t);
503 doc.appendChild(content);
504 return true;
505 }
506
507 /** add an error message, unknown error type */
508 public static boolean addError(Element doc, String text)
509 {
510 return addError(doc, text, ERROR_TYPE_OTHER);
511 }
512
513 /** add an error message */
514 public static boolean addError(Element doc, String text, String error_type)
515 {
516
517 Element content = doc.getOwnerDocument().createElement(ERROR_ELEM);
518 content.setAttribute(ERROR_TYPE_ATT, error_type);
519 Text t = doc.getOwnerDocument().createTextNode(text);
520 content.appendChild(t);
521 doc.appendChild(content);
522 return true;
523 }
524
525 /** add an error message */
526 public static boolean addError(Element doc, Throwable error)
527 {
528 return addError(doc, error, ERROR_TYPE_OTHER);
529 }
530
531 /** add an error message */
532 public static boolean addError(Element doc, Throwable error, String error_type)
533 {
534 error.printStackTrace();
535 return addError(doc, error.toString(), error_type);
536 }
537
538 public static boolean addGSNamespaces(Element elem, boolean include_extension_ns) {
539 if (elem == null) {
540 return false;
541 }
542 elem.setAttribute("xmlns:gsf", GSF_NAMESPACE);
543 elem.setAttribute("xmlns:xsl", XSL_NAMESPACE);
544 elem.setAttribute("xmlns:gslib", GSLIB_NAMESPACE);
545 if (include_extension_ns) {
546 elem.setAttribute("xmlns:util", UTIL_NAMESPACE);
547 elem.setAttribute("xmlns:java", JAVA_NAMESPACE);
548 }
549 return true;
550 }
551
552 /** This adds any namespace attributes from donor_element into main_elem if they are not already there */
553 public static void addMissingNamespaceAttributes(Element main_elem, Element donor_elem) {
554 // are there any new namespaces to be added?
555 NamedNodeMap attributes = donor_elem.getAttributes();
556 for (int i=0; i<attributes.getLength(); i++) {
557 Attr att = (Attr)attributes.item(i);
558 String att_name = att.getName();
559 if (att_name.startsWith("xmlns:")) {
560 //logger.error("found a namespace att "+att_name);
561 if (main_elem.getAttribute(att_name).equals("")) {
562 main_elem.setAttribute(att_name, att.getValue());
563 //logger.error("setting att in main");
564 }
565 }
566 }
567
568
569 }
570 public static Element createMetadataParamList(Document owner, Vector meta_values)
571 {
572
573 Element meta_param_list = owner.createElement(PARAM_ELEM + LIST_MODIFIER);
574 Iterator i = meta_values.iterator();
575 while (i.hasNext())
576 {
577 String next = (String) i.next();
578 Element meta_param = owner.createElement(PARAM_ELEM);
579 meta_param_list.appendChild(meta_param);
580 meta_param.setAttribute(NAME_ATT, "metadata");
581 meta_param.setAttribute(VALUE_ATT, next);
582 }
583 return meta_param_list;
584 }
585
586 /** adds a metadata elem to a list */
587 public static boolean addMetadata(Element list, String meta_name, String meta_value)
588 {
589 if (meta_value == null || meta_value.equals(""))
590 {
591 return false;
592 }
593 Document owner = list.getOwnerDocument();
594 Element data = owner.createElement(METADATA_ELEM);
595 data.setAttribute(NAME_ATT, meta_name);
596 Text t = owner.createTextNode(meta_value);
597 data.appendChild(t);
598 list.appendChild(data);
599 return true;
600
601 }
602
603 /**
604 * copies the metadata out of the metadataList of 'from' into the
605 * metadataList of 'to'
606 */
607 public static boolean mergeMetadataLists(Node to, Node from) {
608 return mergeSpecifiedLists(to, from, METADATA_ELEM);
609 }
610
611 /** copies metadata from meta_list into the metadataList of to **/
612 public static boolean mergeMetadataFromList(Node to, Node meta_list) {
613 return mergeSpecifiedFromList(to, meta_list, METADATA_ELEM);
614 }
615
616
617 public static boolean mergeSpecifiedLists(Node to, Node from, String element_name) {
618 // find the list in the from element
619 Node from_list = getChildByTagName(from, element_name+LIST_MODIFIER);
620 if (from_list == null) {
621 // nothing to copy
622 return false;
623 }
624
625 return mergeSpecifiedFromList(to, from_list, element_name);
626 }
627 public static boolean mergeSpecifiedFromList(Node to, Node from_list, String element_name) {
628 if (from_list == null) {
629 return false;
630 }
631 Document to_owner = to.getOwnerDocument();
632 Node to_list = getChildByTagName(to, element_name+LIST_MODIFIER);
633 if (to_list == null) {
634 // just copy over the whole list
635 to.appendChild(to_owner.importNode(from_list, true));
636 return true;
637 }
638 // otherwise we copy all the elements
639 NodeList from_items = ((Element) from_list).getElementsByTagName(element_name);
640
641 for (int i = 0; i < from_items.getLength(); i++)
642 {
643 to_list.appendChild(to_owner.importNode(from_items.item(i), true));
644 }
645 return true;
646
647 }
648
649 /** copies all the children from from to to */
650 public static boolean mergeElements(Element to, Element from)
651 {
652
653 Document owner = to.getOwnerDocument();
654 Node child = from.getFirstChild();
655 while (child != null)
656 {
657 to.appendChild(owner.importNode(child, true));
658 child = child.getNextSibling();
659 }
660 return true;
661 }
662
663 /** returns the (first) element child of the node n */
664 public static Element getFirstElementChild(Node n)
665 {
666
667 Node child = n.getFirstChild();
668 while (child != null)
669 {
670 if (child.getNodeType() == Node.ELEMENT_NODE)
671 {
672 return (Element) child;
673 }
674 child = child.getNextSibling();
675 }
676 return null; //no element child found
677 }
678
679 /** returns the (first) child element with the given name */
680 public static Node getChildByTagName(Node n, String name)
681 {
682 if (n != null)
683 { // this line is an attempted solution to the NullPointerException mentioned
684 // in trac bug ticket #225. If n is null can't do n.getFirstChild() below. As per bug #225:
685 // getNodeByPath() is called by GS2BrowseAction, which then calls this method.
686 // If n is null, null will be returned which GS2BrowseAction already checks for. It's here
687 // that the NullPointerException was thrown.
688
689 Node child = n.getFirstChild();
690 while (child != null)
691 {
692 if (child.getNodeName().equals(name))
693 {
694 return child;
695 }
696 child = child.getNextSibling();
697 }
698 }
699 return null; //not found
700 }
701
702 /**
703 * returns the (nth) child element with the given name index numbers start
704 * at 0
705 */
706 public static Node getChildByTagNameIndexed(Node n, String name, int index)
707 {
708 if (index == -1)
709 {
710 return getChildByTagName(n, name);
711 }
712 int count = 0;
713 Node child = n.getFirstChild();
714 while (child != null)
715 {
716 if (child.getNodeName().equals(name))
717 {
718 if (count == index)
719 {
720 return child;
721 }
722 else
723 {
724 count++;
725 }
726 }
727 child = child.getNextSibling();
728 }
729 return null; //not found
730 }
731
732 /**
733 * takes an xpath type expression of the form name/name/... and returns the
734 * first node that matches, or null if not found
735 */
736 public static Node getNodeByPath(Node n, String path)
737 {
738
739 String link = GSPath.getFirstLink(path);
740 path = GSPath.removeFirstLink(path);
741 while (!link.equals(""))
742 {
743 n = getChildByTagName(n, link);
744 if (n == null)
745 {
746 return null;
747 }
748 link = GSPath.getFirstLink(path);
749 path = GSPath.removeFirstLink(path);
750 }
751 return n;
752 }
753
754 /**
755 * takes an xpath type expression of the form name/name/... and returns the
756 * first node that matches, or null if not found can include [i] indices.
757 * index numbers start at 0
758 */
759 public static Node getNodeByPathIndexed(Node n, String path)
760 {
761
762 String link = GSPath.getFirstLink(path);
763 int index = GSPath.getIndex(link);
764 if (index != -1)
765 {
766 link = GSPath.removeIndex(link);
767 }
768 path = GSPath.removeFirstLink(path);
769 while (!link.equals(""))
770 {
771 n = getChildByTagNameIndexed(n, link, index);
772 if (n == null)
773 {
774 return null;
775 }
776 link = GSPath.getFirstLink(path);
777 index = GSPath.getIndex(link);
778 if (index != -1)
779 {
780 link = GSPath.removeIndex(link);
781 }
782 path = GSPath.removeFirstLink(path);
783 }
784 return n;
785 }
786
787 public static HashMap<String, Node> getChildrenMap(Node n)
788 {
789
790 HashMap<String, Node> map = new HashMap<String, Node>();
791 Node child = n.getFirstChild();
792 while (child != null)
793 {
794 String name = child.getNodeName();
795 map.put(name, child);
796 child = child.getNextSibling();
797 }
798 return map;
799 }
800
801 public static NodeList getChildrenByTagName(Node n, String name)
802 {
803 MyNodeList node_list = new MyNodeList();
804 Node child = n.getFirstChild();
805 while (child != null)
806 {
807 if (child.getNodeName().equals(name))
808 {
809 node_list.addNode(child);
810 }
811 child = child.getNextSibling();
812 }
813 return node_list;
814 }
815
816 public static NodeList getChildrenByTagNameNS(Node n, String namespace, String local_name)
817 {
818 MyNodeList node_list = new MyNodeList();
819 Node child = n.getFirstChild();
820 while (child != null)
821 {
822 if (child.getNodeType() == Node.ELEMENT_NODE && child.getNamespaceURI() != null && child.getNamespaceURI().equals(namespace) && child.getLocalName() != null && child.getLocalName().equals(local_name))
823 {
824 node_list.addNode(child);
825 }
826 child = child.getNextSibling();
827 }
828 return node_list;
829 }
830
831 /** Duplicates an element, but gives it a new name */
832 public static Element duplicateWithNewName(Document owner, Element element, String element_name, boolean with_attributes)
833 {
834 return duplicateWithNewNameNS(owner, element, element_name, null, with_attributes);
835 }
836
837 /** Duplicates an element, but gives it a new name */
838 public static Element duplicateWithNewNameNS(Document owner, Element element, String element_name, String namespace_uri, boolean with_attributes)
839 {
840 Element duplicate;
841 if (namespace_uri == null)
842 {
843 duplicate = owner.createElement(element_name);
844 }
845 else
846 {
847 duplicate = owner.createElementNS(namespace_uri, element_name);
848 }
849
850 // Copy element attributes
851 if (with_attributes)
852 {
853 NamedNodeMap attributes = element.getAttributes();
854 for (int i = 0; i < attributes.getLength(); i++)
855 {
856 Node attribute = attributes.item(i);
857 duplicate.setAttribute(attribute.getNodeName(), attribute.getNodeValue());
858 }
859 }
860
861 // Copy element children
862 NodeList children = element.getChildNodes();
863 for (int i = 0; i < children.getLength(); i++)
864 {
865 Node child = children.item(i);
866 duplicate.appendChild(owner.importNode(child, true));
867 }
868
869 return duplicate;
870 }
871
872 public static void copyAllChildren(Element to, Element from)
873 {
874
875 Document to_doc = to.getOwnerDocument();
876 Node child = from.getFirstChild();
877 while (child != null)
878 {
879 to.appendChild(to_doc.importNode(child, true));
880 child = child.getNextSibling();
881 }
882 }
883
884 public static void copyNode(Element to_elem, Node original_element) {
885 to_elem.appendChild(to_elem.getOwnerDocument().importNode(original_element, true));
886
887 }
888
889 public static void copyNamedElement(Element to, Element from, String elem_name) {
890
891 Document to_doc = to.getOwnerDocument();
892 Node child = from.getFirstChild();
893 while (child != null) {
894 if (child.getNodeName().equals(elem_name)) {
895 to.appendChild(to_doc.importNode(child, true));
896 return;
897 }
898 child = child.getNextSibling();
899 }
900 }
901
902 /* Have an element with a set of children, attributes name="x". Replace the specified item in the list with new_item. */
903 /* this assumes we only have children of the same node name. if going tro have mixed lists, need to test on node name as well */
904 public static void replaceNamedItemInList(Element item_list, String item_node_name, String name_att, String item_name, Element new_item) {
905 Node child = item_list.getFirstChild();
906 while(child != null) {
907 if (child.getNodeName().equals(item_node_name) && ((Element)child).getAttribute(name_att).equals(item_name)) {
908 //replace the element
909 item_list.insertBefore(item_list.getOwnerDocument().importNode(new_item, true), child);
910 item_list.removeChild(child);
911 return;
912 }
913 child = child.getNextSibling();
914 }
915
916 }
917 /**
918 * Given a Node representing an Element or Document, will return the
919 * Element/docroot Element. Returns null if the Node was not an element.
920 */
921 public static Element nodeToElement(Node node)
922 {
923 if (node == null)
924 {
925 return null;
926 }
927 short nodeType = node.getNodeType();
928
929 if (nodeType == Node.DOCUMENT_NODE)
930 {
931 Document docNode = (Document) node;
932 return docNode.getDocumentElement();
933 }
934 else if (nodeType == Node.ELEMENT_NODE)
935 {
936 return (Element) node;
937 }
938 else
939 {
940 String message = "Expecting Document or Element node type but got " + node.getNodeName() + "\nReturning null";
941 System.err.println(message);
942 logger.warn(message);
943 return null;
944 }
945 }
946
947
948 /** returns a basic request message */
949 public static Element createBasicRequest(Document owner, String request_type, String to, UserContext userContext)
950 {
951 Element request = owner.createElement(REQUEST_ELEM);
952 request.setAttribute(TO_ATT, to);
953 request.setAttribute(TYPE_ATT, request_type);
954 if (userContext == null) {
955 return request; // should we allow this??
956 }
957 request.setAttribute(LANG_ATT, userContext.getLanguage());
958 Element userContextElem = owner.createElement("userContext");
959 request.appendChild(userContextElem);
960 userContextElem.setAttribute(LANG_ATT, userContext.getLanguage());
961 userContextElem.setAttribute(USERNAME_ATT, userContext.getUsername());
962 userContextElem.setAttribute(USER_ID_ATT, userContext.getUserID());
963 userContextElem.setAttribute(GROUPS_ATT, userContext.getGroupsString());
964 userContextElem.setAttribute(EDIT_ENABLED_ATT, userContext.getEditEnabled());
965
966 return request;
967 }
968
969 public static Element createBasicResponse(Document owner, String from)
970 {
971 Element response = owner.createElement(RESPONSE_ELEM);
972 response.setAttribute(FROM_ATT, from);
973 response.setAttribute(TYPE_ATT, REQUEST_TYPE_PROCESS);
974 return response;
975 }
976
977 public static Element createMetadataElement(Document owner, String name, String value)
978 {
979 Element metaElem = owner.createElement(METADATA_ELEM);
980 metaElem.setAttribute(NAME_ATT, name);
981 metaElem.setAttribute(VALUE_ATT, value);
982 return metaElem;
983 }
984
985 public static Element createTextElement(Document owner, String elem_name, String text)
986 {
987 Element e = owner.createElement(elem_name);
988 Text t = owner.createTextNode(text);
989 e.appendChild(t);
990 return e;
991
992 }
993
994 public static Element createTextElement(Document owner, String elem_name, String text, String att_name, String att_value)
995 {
996 Element e = owner.createElement(elem_name);
997 e.setAttribute(att_name, att_value);
998 Text t = owner.createTextNode(text);
999 e.appendChild(t);
1000 return e;
1001
1002 }
1003
1004 public static Element createDisplayTextElement(Document owner, String text_name, String text)
1005 {
1006 Element e = owner.createElement(DISPLAY_TEXT_ELEM);
1007 e.setAttribute(NAME_ATT, text_name);
1008 Text t = owner.createTextNode(text);
1009 e.appendChild(t);
1010 return e;
1011
1012 }
1013
1014 // for parameters where value is an attribute
1015 public static Element createParameter(Document owner, String name, String value)
1016 {
1017 Element param = owner.createElement(PARAM_ELEM);
1018 param.setAttribute(NAME_ATT, name);
1019 param.setAttribute(VALUE_ATT, value);
1020 return param;
1021 }
1022
1023 // for parameters where value is a text node
1024 public static Element createParameter2(Document owner, String name, String value) {
1025 Element param = owner.createElement(PARAM_ELEM);
1026 param.setAttribute(NAME_ATT, name);
1027 param.appendChild(owner.createTextNode(value));
1028 return param;
1029 }
1030
1031 public static void addParameterToList(Element param_list, String name, String value) {
1032 Element p = createParameter(param_list.getOwnerDocument(), name, value);
1033 param_list.appendChild(p);
1034 }
1035 public static void addParameter2ToList(Element param_list, String name, String value) {
1036 Element p = createParameter2(param_list.getOwnerDocument(), name, value);
1037 param_list.appendChild(p);
1038 }
1039 public static void addParametersToList(Element param_list, HashMap params)
1040 {
1041 if (params == null)
1042 {
1043 return;
1044 }
1045
1046 Set items = params.entrySet();
1047 Iterator i = items.iterator();
1048 Document owner = param_list.getOwnerDocument();
1049 while (i.hasNext())
1050 {
1051 Map.Entry m = (Map.Entry) i.next();
1052 param_list.appendChild(createParameter(owner, (String) m.getKey(), (String) m.getValue()));
1053 }
1054
1055 }
1056
1057 public static Element createParameterDescription(Document owner, String id, String display_name, String type, String default_value, String[] option_ids, String[] option_names)
1058 {
1059
1060 Element p = owner.createElement(PARAM_ELEM);
1061 p.setAttribute(NAME_ATT, id);
1062 p.setAttribute(TYPE_ATT, type);
1063 p.appendChild(createDisplayTextElement(owner, DISPLAY_TEXT_NAME, display_name));
1064
1065 if (default_value != null)
1066 {
1067 p.setAttribute(DEFAULT_ATT, default_value);
1068 }
1069 if (option_ids != null && option_names != null)
1070 {
1071 for (int i = 0; i < option_ids.length; i++)
1072 {
1073 Element e = owner.createElement(PARAM_OPTION_ELEM);
1074 e.setAttribute(NAME_ATT, option_ids[i]);
1075 e.appendChild(createDisplayTextElement(owner, DISPLAY_TEXT_NAME, option_names[i]));
1076 p.appendChild(e);
1077 }
1078 }
1079 return p;
1080 }
1081
1082 public static Element createParameterDescription2(Document owner, String id, String display_name, String type, String default_value, ArrayList<String> option_ids, ArrayList<String> option_names)
1083 {
1084
1085 Element p = owner.createElement(PARAM_ELEM);
1086 p.setAttribute(NAME_ATT, id);
1087 p.setAttribute(TYPE_ATT, type);
1088 p.appendChild(createDisplayTextElement(owner, DISPLAY_TEXT_NAME, display_name));
1089 if (default_value != null)
1090 {
1091 p.setAttribute(DEFAULT_ATT, default_value);
1092 }
1093 if (option_ids != null && option_names != null)
1094 {
1095 for (int i = 0; i < option_ids.size(); i++)
1096 {
1097 Element e = owner.createElement(PARAM_OPTION_ELEM);
1098 e.setAttribute(NAME_ATT, option_ids.get(i));
1099 e.appendChild(createDisplayTextElement(owner, DISPLAY_TEXT_NAME, option_names.get(i)));
1100 p.appendChild(e);
1101 }
1102 }
1103 return p;
1104 }
1105
1106 /** returns the element parent/node_name[@attribute_name='attribute_value']
1107 if attribute_value is null, just returns the first one with that attribute */
1108 public static Element getNamedElement(Element parent, String node_name, String attribute_name, String attribute_value)
1109 {
1110
1111 NodeList children = parent.getChildNodes();
1112 for (int i = 0; i < children.getLength(); i++)
1113 {
1114 Node child = children.item(i);
1115 if (child.getNodeName().equals(node_name))
1116 {
1117 String att_val = ((Element) child).getAttribute(attribute_name);
1118 if (!att_val.equals("") ) {
1119 if (attribute_value == null || att_val.equals(attribute_value)) {
1120 return (Element) child;
1121 }
1122 }
1123 }
1124 } // for each child
1125 // not found
1126 return null;
1127 }
1128
1129 public static Element getNamedElementNS(Element parent, String namespace_uri, String node_local_name, String attribute_name, String attribute_value)
1130 {
1131 NodeList children = parent.getChildNodes();
1132 for (int i = 0; i < children.getLength(); i++)
1133 {
1134 Node child = children.item(i);
1135 if (child.getNodeType() == Node.ELEMENT_NODE && child.getNamespaceURI() != null && child.getNamespaceURI().equals(namespace_uri) && child.getLocalName().equals(node_local_name))
1136 {
1137 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
1138 return (Element) child;
1139 }
1140 }
1141 // not found
1142 return null;
1143 }
1144
1145 public static NodeList getNamedElementsNS(Element parent, String namespace_uri, String node_local_name, String attribute_name, String attribute_value)
1146 {
1147 MyNodeList result = new MyNodeList();
1148 NodeList children = parent.getChildNodes();
1149 for (int i = 0; i < children.getLength(); i++)
1150 {
1151 Node child = children.item(i);
1152 if (child.getNodeType() == Node.ELEMENT_NODE && child.getNamespaceURI() != null && child.getNamespaceURI().equals(namespace_uri) && child.getLocalName().equals(node_local_name))
1153 {
1154 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
1155 result.addNode(child);
1156 }
1157 }
1158 return result;
1159 }
1160
1161 public static NodeList getElementsWithAttributesNS(Element parent, String namespace_uri, String node_local_name, String[] attribute_names, String[] attribute_values)
1162 {
1163 if (attribute_names.length == 0 || attribute_names.length != attribute_values.length)
1164 {
1165 return new MyNodeList();
1166 }
1167
1168 MyNodeList result = new MyNodeList();
1169
1170 NodeList matchingNodes = getNamedElementsNS(parent, namespace_uri, node_local_name, attribute_names[0], attribute_values[0]);
1171 for (int i = 0; i < matchingNodes.getLength(); i++)
1172 {
1173 Element current = (Element) matchingNodes.item(i);
1174 boolean nodeMatches = true;
1175 for (int j = 1; j < attribute_names.length; j++)
1176 {
1177 String currentName = attribute_names[j];
1178 String currentValue = attribute_values[j];
1179 if (!current.getAttribute(currentName).equals(currentValue))
1180 {
1181 nodeMatches = false;
1182 break;
1183 }
1184 }
1185
1186 if (nodeMatches)
1187 {
1188 result.addNode(current);
1189 }
1190 }
1191
1192 return result;
1193 }
1194
1195 public static void removeElementsWithAttributesNS(Element parent, String namespace_uri, String node_local_name, String[] attribute_names, String[] attribute_values)
1196 {
1197 NodeList matchingNodes = getElementsWithAttributesNS(parent, namespace_uri, node_local_name, attribute_names, attribute_values);
1198 for (int i = 0; i < matchingNodes.getLength(); i++)
1199 {
1200 parent.removeChild(matchingNodes.item(i));
1201 }
1202 }
1203
1204 // In element main, tries to find any previous occurrence of elements with xsl-template-name=templateName,
1205 // and whose named attribute (attributeName) has the same value as the same attribute in node.
1206 // If this is the case, such a previous occurrence is removed from element main, since
1207 // the new node will contain a more specific redefinition of this element.
1208 public static void removeNamedElementNS(Element parent, String namespace_uri, String node_local_name, String attribute_name, String attribute_value)
1209 {
1210 if (attribute_value.equals(""))
1211 {
1212 // it has no identifying attribute, so we can't find any matches
1213 return;
1214 }
1215
1216 Element old_elem = getNamedElementNS(parent, namespace_uri, node_local_name, attribute_name, attribute_value);
1217 if (old_elem != null)
1218 {
1219 parent.removeChild(old_elem);
1220 }
1221 }
1222
1223 public static void removeNamedElementsNS(Element parent, String namespace, String node_local_name, String attribute_name, String attribute_value)
1224 {
1225 if (attribute_value.equals(""))
1226 {
1227 // it has no identifying attribute, so we can't find any matches
1228 return;
1229 }
1230
1231 NodeList children = parent.getChildNodes();
1232 for (int i = children.getLength() - 1; i >= 0; i--)
1233 {
1234 Node child = children.item(i);
1235 if (child.getNodeType() == Node.ELEMENT_NODE && child.getNamespaceURI() != null && child.getNamespaceURI().equals(namespace) && child.getLocalName() != null && child.getLocalName().equals(node_local_name))
1236 {
1237 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
1238 parent.removeChild(child);
1239 }
1240 }
1241 }
1242
1243 /**
1244 * returns a NodeList of elements:
1245 * ancestor/node_name[@attribute_name='attribute_value']
1246 */
1247 public static NodeList getNamedElements(Element ancestor, String node_name, String attribute_name, String attribute_value)
1248 {
1249 MyNodeList node_list = new MyNodeList();
1250 NodeList children = ancestor.getElementsByTagName(node_name);
1251
1252 if (children != null && children.getLength() > 0)
1253 {
1254
1255 for (int i = 0; i < children.getLength(); i++)
1256 {
1257 Node child = children.item(i);
1258 if (child.getNodeName().equals(node_name))
1259 {
1260 if (((Element) child).getAttribute(attribute_name).equals(attribute_value))
1261 node_list.addNode(child);
1262 }
1263 }
1264 }
1265 return node_list;
1266 }
1267
1268 public static Element getLastElementByTagNameNS(Element main, String namespace, String node_name)
1269 {
1270 NodeList nodes = main.getElementsByTagNameNS(namespace, node_name);
1271 int len = nodes.getLength();
1272 if (len == 0)
1273 {
1274 return null;
1275 }
1276 return (Element) nodes.item(len - 1);
1277 }
1278
1279 public static int SORT_TYPE_STRING = 0;
1280 public static int SORT_TYPE_INT = 1;
1281 public static int SORT_TYPE_FLOAT = 2;
1282
1283 // sort type:
1284 public static Element insertIntoOrderedList(Element parent_node, String node_name, Element start_from_elem, Element new_elem, String sort_att, boolean descending)
1285 {
1286 if (new_elem == null)
1287 return null;
1288 Element cloned_elem = (Element) parent_node.getOwnerDocument().importNode(new_elem, true);
1289 if (start_from_elem == null)
1290 {
1291 parent_node.appendChild(cloned_elem);
1292 return cloned_elem;
1293 }
1294
1295 Node current_node = start_from_elem;
1296 String insert_att = cloned_elem.getAttribute(sort_att);
1297 String list_att = start_from_elem.getAttribute(sort_att);
1298 while ((!descending && list_att.compareTo(insert_att) < 0) || (descending && list_att.compareTo(insert_att) > 0))
1299 {
1300 current_node = current_node.getNextSibling();
1301 if (current_node == null)
1302 break; // end of the list
1303 if (!current_node.getNodeName().equals(node_name))
1304 {
1305 continue; // not a valid node
1306 }
1307 list_att = ((Element) current_node).getAttribute(sort_att);
1308 }
1309
1310 parent_node.insertBefore(cloned_elem, current_node);
1311 return cloned_elem;
1312 }
1313
1314 public static String getMetadataValue(Element metadata_list, String name) {
1315 Element meta = getNamedElement(metadata_list, METADATA_ELEM, NAME_ATT, name);
1316 if (meta == null) {
1317 return "";
1318 }
1319 String att_value = meta.getAttribute(VALUE_ATT);
1320 if (att_value.equals("")) {
1321 // try the text
1322 att_value = getNodeText(meta);
1323 }
1324 return att_value;
1325 }
1326
1327 // replaces < > " ' & in the original with their entities
1328 public static String xmlSafe(String original)
1329 {
1330
1331 StringBuffer filtered = new StringBuffer(original.length());
1332 char c;
1333 for (int i = 0; i < original.length(); i++)
1334 {
1335 c = original.charAt(i);
1336 if (c == '>')
1337 {
1338 filtered.append("&gt;");
1339 }
1340 else if (c == '<')
1341 {
1342 filtered.append("&lt;");
1343 }
1344 else if (c == '"')
1345 {
1346 filtered.append("&quot;");
1347 }
1348 else if (c == '&')
1349 {
1350 filtered.append("&amp;");
1351 }
1352 else if (c == '\'')
1353 {
1354 filtered.append("&apos;");
1355 }
1356 else
1357 {
1358 filtered.append(c);
1359 }
1360 }
1361 return filtered.toString();
1362 }
1363
1364 // replaces < > " ' & entities with their originals
1365 public static String unXmlSafe(String original)
1366 {
1367
1368 StringBuffer filtered = new StringBuffer(original.length());
1369 char c;
1370 for (int i = 0; i < original.length(); i++)
1371 {
1372 c = original.charAt(i);
1373 if (c == '&')
1374 {
1375 int pos = original.indexOf(";", i);
1376 String entity = original.substring(i + 1, pos);
1377 if (entity.equals("gt"))
1378 {
1379 filtered.append(">");
1380 }
1381 else if (entity.equals("lt"))
1382 {
1383 filtered.append("<");
1384 }
1385 else if (entity.equals("apos"))
1386 {
1387 filtered.append("'");
1388 }
1389 else if (entity.equals("amp"))
1390 {
1391 filtered.append("&");
1392 }
1393 else if (entity.equals("quot"))
1394 {
1395 filtered.append("\"");
1396 }
1397 else
1398 {
1399 filtered.append("&" + entity + ";");
1400 }
1401 i = pos;
1402 }
1403 else
1404 {
1405 filtered.append(c);
1406 }
1407 }
1408 return filtered.toString();
1409 }
1410
1411 public static void printXMLNode(Node e, boolean printText)
1412 {
1413 printXMLNode(e, 0, printText);
1414 }
1415
1416 public static String xmlNodeToString(Node e)
1417 {
1418 StringBuffer sb = new StringBuffer("");
1419 xmlNodeToString(sb, e, true, "\t", 0);
1420 return sb.toString();
1421 }
1422
1423 public static void xmlNodeToString(StringBuffer sb, Node e, boolean indent, String indentString, int depth)
1424 {
1425 if (e.getNodeType() == Node.TEXT_NODE)
1426 {
1427 if (e.getNodeValue() != "")
1428 {
1429 String text = e.getNodeValue();
1430 if (text != null)
1431 {
1432 text = text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("^[\\n\\r\\t\\s]*", "").replaceAll("[\\n\\r\\t\\s]*$", "");
1433 sb.append(text);
1434 }
1435 }
1436 return;
1437 }
1438
1439 if (e.getNodeType() == Node.COMMENT_NODE)
1440 {
1441 if (e.getNodeValue() != "")
1442 {
1443 sb.append("<!--" + e.getNodeValue() + "-->");
1444 }
1445 return;
1446 }
1447
1448 if (indent)
1449 {
1450 for (int i = 0; i < depth; i++)
1451 {
1452 sb.append(indentString);
1453 }
1454 }
1455
1456 sb.append('<');
1457 sb.append(e.getNodeName());
1458 NamedNodeMap attrs = e.getAttributes();
1459 if (attrs != null)
1460 {
1461 for (int i = 0; i < attrs.getLength(); i++)
1462 {
1463 Node attr = attrs.item(i);
1464 sb.append(' ');
1465 sb.append(attr.getNodeName());
1466 sb.append("=\"");
1467 sb.append(attr.getNodeValue().replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"));
1468 sb.append('"');
1469 }
1470 }
1471
1472 if (e.hasChildNodes())
1473 {
1474 boolean hasElements = false;
1475 boolean indentSwapped = false;
1476
1477 Node child = e.getFirstChild();
1478 do
1479 {
1480 if (child.getNodeType() == Node.ELEMENT_NODE)
1481 {
1482 hasElements = true;
1483 }
1484 if (child.getNodeType() == Node.TEXT_NODE && indent)
1485 {
1486 if (child.getNodeValue() != null && child.getNodeValue().trim().length() > 0)
1487 {
1488 indentSwapped = true;
1489 indent = false;
1490 }
1491 }
1492 } while ((child = child.getNextSibling()) != null);
1493
1494 sb.append(">");
1495 if (hasElements && indent)
1496 {
1497 sb.append("\n");
1498 }
1499
1500 child = e.getFirstChild();
1501 do
1502 {
1503 xmlNodeToString(sb, child, indent, indentString, depth + 1);
1504 } while ((child = child.getNextSibling()) != null);
1505
1506 if (indent)
1507 {
1508 for (int i = 0; i < depth; i++)
1509 {
1510 sb.append(indentString);
1511 }
1512 }
1513
1514 sb.append("</" + e.getNodeName() + ">");
1515
1516 if ((hasElements && indent) || indentSwapped)
1517 {
1518 sb.append("\n");
1519 }
1520 }
1521 else
1522 {
1523 sb.append("/>");
1524
1525 if (indent)
1526 {
1527 sb.append("\n");
1528 }
1529 }
1530
1531 /*
1532 boolean hasElements = false;
1533 boolean indentSwapped = false;
1534 for (int i = 0; i < children.getLength(); i++)
1535 {
1536 if (children.item(i).getNodeType() == Node.ELEMENT_NODE)
1537 {
1538 hasElements = true;
1539 }
1540 if (children.item(i).getNodeType() == Node.TEXT_NODE && indent)
1541 {
1542 if (children.item(i).getNodeValue() != null && children.item(i).getNodeValue().trim().length() > 0)
1543 {
1544 indentSwapped = true;
1545 indent = false;
1546 }
1547 }
1548 }
1549
1550 if (children == null || children.getLength() == 0)
1551 {
1552 sb.append("/>");
1553
1554 if (indent)
1555 {
1556 sb.append("\n");
1557 }
1558 }
1559 else
1560 {
1561 sb.append(">");
1562 if (hasElements && indent)
1563 {
1564 sb.append("\n");
1565 }
1566
1567 int len = children.getLength();
1568 for (int i = 0; i < len; i++)
1569 {
1570 xmlNodeToString(sb, children.item(i), indent, indentString, depth + 1);
1571 }
1572
1573 if (indent)
1574 {
1575 for (int i = 0; i < depth; i++)
1576 {
1577 sb.append(indentString);
1578 }
1579 }
1580
1581 sb.append("</" + e.getNodeName() + ">");
1582
1583 if ((hasElements && indent) || indentSwapped)
1584 {
1585 sb.append("\n");
1586 }
1587 }
1588 */
1589 }
1590
1591 public static void printXMLNode(Node e, int depth, boolean printText)
1592 { //recursive method call using DOM API...
1593
1594 if (e == null)
1595 {
1596 return;
1597 }
1598
1599 for (int i = 0; i < depth; i++)
1600 System.out.print(' ');
1601
1602 if (e.getNodeType() == Node.TEXT_NODE)
1603 {
1604 if (printText)
1605 {
1606 System.out.println(e.getNodeValue());
1607 }
1608 else
1609 {
1610 System.out.println("text");
1611 }
1612 return;
1613 }
1614
1615 System.out.print('<');
1616 System.out.print(e.getNodeName());
1617 NamedNodeMap attrs = e.getAttributes();
1618
1619 if (attrs != null)
1620 {
1621 for (int i = 0; i < attrs.getLength(); i++)
1622 {
1623 Node attr = attrs.item(i);
1624 System.out.print(' ');
1625 System.out.print(attr.getNodeName());
1626 System.out.print("=\"");
1627 System.out.print(attr.getNodeValue());
1628 System.out.print('"');
1629 }
1630 }
1631
1632 NodeList children = e.getChildNodes();
1633
1634 if (children == null || children.getLength() == 0)
1635 System.out.println("/>");
1636 else
1637 {
1638
1639 System.out.println('>');
1640
1641 int len = children.getLength();
1642 for (int i = 0; i < len; i++)
1643 {
1644 printXMLNode(children.item(i), depth + 1, printText);
1645 }
1646
1647 for (int i = 0; i < depth; i++)
1648 System.out.print(' ');
1649
1650 System.out.println("</" + e.getNodeName() + ">");
1651 }
1652 }
1653
1654 private static void elementToLogAsString(String prefix, Element e, boolean indent, boolean debugEncoding)
1655 {
1656 String str = prefix + "\n" + elementToString(e, indent, debugEncoding);
1657 System.err.println(str);
1658 logger.info(str);
1659 }
1660
1661 // hex/unicode codepoint used only for those chars that are beyond printable/basic ASCII
1662 public static void elementToLogAsUnicodeDebugString(String prefix, Element e, boolean indent)
1663 {
1664 elementToLogAsString(prefix, e, indent, true);
1665 }
1666
1667 public static void elementToLogAsString(String prefix, Element e, boolean indent)
1668 {
1669 elementToLogAsString(prefix, e, indent, false);
1670 }
1671
1672 // pass in debugEncoding=true to investigate encoding issues. This function will then return non-basic ASCII characters in hex
1673 private static String elementToString(Element e, boolean indent, boolean debugEncoding)
1674 {
1675 String str = "";
1676 try
1677 {
1678 TransformerFactory tf = TransformerFactory.newInstance();
1679 Transformer trans = tf.newTransformer();
1680 StringWriter sw = new StringWriter();
1681 if (indent)
1682 {
1683 trans.setOutputProperty(OutputKeys.INDENT, "yes");
1684 }
1685 else
1686 {
1687 trans.setOutputProperty(OutputKeys.INDENT, "no");
1688 }
1689 trans.transform(new DOMSource(e), new StreamResult(sw));
1690 str += sw.toString();
1691
1692 // if debugging encoding issues, then encode unicode code pts as hex for all but non-alphanumeric and space/tab/newline chars
1693 if(debugEncoding) str = Misc.debugUnicodeString(str);
1694 }
1695 catch (Exception ex)
1696 {
1697 str += "Exception: couldn't write " + e + " to log";
1698 }
1699 finally
1700 {
1701 return str;
1702 }
1703 }
1704
1705 public static String elementToString(Element e, boolean indent)
1706 {
1707 return elementToString(e, indent, false);
1708 }
1709
1710 // hex/unicode codepoint used only for those chars that are beyond printable/basic ASCII
1711 public static String elementToUnicodeDebugString(Element e, boolean indent)
1712 {
1713 return elementToString(e, indent, true);
1714 }
1715
1716 public static ArrayList<String> getGroupsFromSecurityResponse(Element securityResponse)
1717 {
1718 ArrayList<String> groups = new ArrayList<String>();
1719
1720 Element groupList = (Element) getChildByTagName(securityResponse, GROUP_ELEM + LIST_MODIFIER);
1721 if (groupList == null)
1722 {
1723 return groups;
1724 }
1725
1726 NodeList groupElems = getChildrenByTagName(groupList, GROUP_ELEM);
1727
1728 for (int i = 0; i < groupElems.getLength(); i++)
1729 {
1730 Element groupElem = (Element) groupElems.item(i);
1731 // an empty attribute will return "". some code depends on having "" for groups, so leave it in for now.
1732 groups.add(groupElem.getAttribute(NAME_ATT));
1733 }
1734
1735 return groups;
1736 }
1737
1738}
Note: See TracBrowser for help on using the repository browser.