source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/XSLTUtil.java@ 29175

Last change on this file since 29175 was 29175, checked in by ak19, 10 years ago

Fixing off by one error of boolean operators in the GS3 search form interface. Kathy had located the problem in XSLUtil.getNumberedItem(). Fixed it by using String.split instead of StringUtils.split, since the latter skipped empty tokens.

  • Property svn:keywords set to Author Date Id Revision
File size: 20.5 KB
Line 
1/*
2 * XSLTUtil.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.ByteArrayInputStream;
22import java.io.File;
23import java.text.SimpleDateFormat;
24import java.util.ArrayList;
25import java.util.Date;
26import java.util.Enumeration;
27import java.util.HashMap;
28import java.util.Locale;
29
30import javax.xml.parsers.DocumentBuilder;
31import javax.xml.parsers.DocumentBuilderFactory;
32
33import net.tanesha.recaptcha.ReCaptcha;
34import net.tanesha.recaptcha.ReCaptchaFactory;
35
36import org.apache.commons.lang3.StringUtils;
37import org.apache.log4j.Logger;
38import org.greenstone.util.GlobalProperties;
39import org.w3c.dom.Node;
40
41/**
42 * a class to contain various static methods that are used by the xslt
43 * stylesheets
44 */
45public class XSLTUtil
46{
47 protected static HashMap<String, ArrayList<String>> _foundTableValues = new HashMap<String, ArrayList<String>>();
48 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.XSLTUtil.class.getName());
49 protected static HashMap<String, String> _stringVariables = new HashMap<String, String>();
50
51 public static void storeString(String name, String value)
52 {
53 _stringVariables.put(name, value);
54 }
55
56 public static String getString(String name)
57 {
58 return _stringVariables.get(name);
59 }
60
61 /* some tests */
62 public static boolean equals(String s1, String s2)
63 {
64 return s1.equals(s2);
65 }
66
67 public static boolean notEquals(String s1, String s2)
68 {
69 return !s1.equals(s2);
70 }
71
72 public static boolean exists(String s1, String s2)
73 {
74 return !s1.equals("");
75 }
76
77 public static boolean contains(String s1, String s2)
78 {
79 return (s1.indexOf(s2) != -1);
80 }
81
82 public static boolean startsWith(String s1, String s2)
83 {
84 return s1.startsWith(s2);
85 }
86
87 public static boolean endsWith(String s1, String s2)
88 {
89 return s1.endsWith(s2);
90 }
91
92 public static boolean lessThan(String s1, String s2)
93 {
94 return (s1.compareTo(s2) < 0);
95 }
96
97 public static boolean lessThanOrEquals(String s1, String s2)
98 {
99 return (s1.compareTo(s2) <= 0);
100 }
101
102 public static boolean greaterThan(String s1, String s2)
103 {
104 return (s1.compareTo(s2) > 0);
105 }
106
107 public static boolean greaterThanOrEquals(String s1, String s2)
108 {
109 return (s1.compareTo(s2) >= 0);
110 }
111
112 public static boolean oidIsMatchOrParent(String first, String second)
113 {
114 if (first.equals(second))
115 {
116 return true;
117 }
118
119 String[] firstParts = first.split(".");
120 String[] secondParts = second.split(".");
121
122 if (firstParts.length >= secondParts.length)
123 {
124 return false;
125 }
126
127 for (int i = 0; i < firstParts.length; i++)
128 {
129 if (!firstParts[i].equals(secondParts[i]))
130 {
131 return false;
132 }
133 }
134
135 return true;
136 }
137
138 public static String oidDocumentRoot(String oid)
139 {
140 String[] oidParts = oid.split("\\.");
141
142 return oidParts[0];
143 }
144
145 public static String replace(String orig, String match, String replacement)
146 {
147 return orig.replace(match, replacement);
148 }
149
150 public static String getNumberedItem(String list, int number)
151 {
152 String[] items = list.split(",", -1); //String[] items = StringUtils.split(list, ",", -1);
153 // Using StringUtils.split() causes an off-by-one error for the boolean operators (fqk)
154 // where boolean operators combining rows in multiforms are shifted up by 1 row.
155
156 if (items.length > number)
157 {
158 return items[number];
159 }
160 return ""; // index out of bounds
161 }
162
163 /**
164 * Generates links to equivalent documents for a document with a default
165 * document icon/type. Links are generated from the parameters: a list of
166 * document icons which are each in turn embedded in the matching starting
167 * link tag in the list of docStartLinks (these starting links link to the
168 * equivalent documents in another format). Each link's start tag is closed
169 * with the corresponding closing tag in the docEndLinks list. Parameter
170 * token is the list separator. Parameter divider is the string that should
171 * separate each final link generated from the next. Returns a string that
172 * represents a sequence of links to equivalent documents, where the anchor
173 * is a document icon.
174 */
175 public static String getEquivDocLinks(String token, String docIconsString, String docStartLinksString, String docEndLinksString, String divider)
176 {
177 String[] docIcons = StringUtils.split(docIconsString, token, -1);
178 String[] startLinks = StringUtils.split(docStartLinksString, token, -1);
179 String[] endLinks = StringUtils.split(docEndLinksString, token, -1);
180
181 StringBuffer buffer = new StringBuffer();
182 for (int i = 0; i < docIcons.length; i++)
183 {
184 if (i > 0)
185 {
186 buffer.append(divider);
187 }
188 buffer.append(startLinks[i] + docIcons[i] + endLinks[i]);
189 }
190
191 return buffer.toString();
192 }
193
194 public static String getInterfaceText(String interface_name, String lang, String key)
195 {
196 return getInterfaceText(interface_name, lang, key, null);
197 }
198
199 public static String getInterfaceText(String interface_name, String lang, String key, String args_str)
200 {
201 key = key.replaceAll("__INTERFACE_NAME__", interface_name);
202
203 String[] args = null;
204 if (args_str != null && !args_str.equals(""))
205 {
206 args = StringUtils.split(args_str, ";");
207 }
208 Dictionary dict = new Dictionary("interface_" + interface_name, lang);
209 String result = dict.get(key, args);
210 if (result == null)
211 { // not found
212 //if not found, search a separate subdirectory named by the interface name
213 String sep_interface_dir = interface_name + File.separatorChar + lang + File.separatorChar + "interface";
214 dict = new Dictionary(sep_interface_dir, lang);
215 result = dict.get(key, args);
216 if (result != null)
217 {
218 result = result.replaceAll("__INTERFACE_NAME__", interface_name);
219 return result;
220 }
221 }
222
223 if (result == null && !interface_name.equals("default"))
224 { // not found, try the default interface
225 dict = new Dictionary("interface_default", lang);
226 result = dict.get(key, args);
227 }
228
229 if (result == null)
230 { // not found
231 return "_" + key + "_";
232 }
233 result = result.replaceAll("__INTERFACE_NAME__", interface_name);
234 return result;
235 }
236
237 public static String getInterfaceText(String interfaceName, String dictionaryName, String lang, String key, String args_str)
238 {
239 key = key.replaceAll("__INTERFACE_NAME__", interfaceName);
240
241 String[] args = null;
242 if (args_str != null && !args_str.equals(""))
243 {
244 args = StringUtils.split(args_str, ";");
245 }
246 Dictionary dict = new Dictionary(dictionaryName, lang);
247 String result = dict.get(key, args);
248 if (result == null)
249 { // not found
250 //if not found, search a separate subdirectory named by the interface name
251 String sep_interface_dir = interfaceName + File.separatorChar + lang + File.separatorChar + "interface";
252 dict = new Dictionary(sep_interface_dir, lang);
253 result = dict.get(key, args);
254 if (result != null)
255 {
256 result = result.replaceAll("__INTERFACE_NAME__", interfaceName);
257 return result;
258 }
259 }
260
261 if (result == null && !interfaceName.equals("default"))
262 { // not found, try the default interface
263 dict = new Dictionary("interface_default", lang);
264 result = dict.get(key, args);
265 }
266
267 if (result == null)
268 { // not found
269 return "_" + key + "_";
270 }
271 result = result.replaceAll("__INTERFACE_NAME__", interfaceName);
272 return result;
273 }
274
275 public static String getInterfaceTextWithDOM(String interface_name, String lang, String key, Node arg_node)
276 {
277 String[] args = new String[1];
278
279 String node_str = XMLConverter.getString(arg_node);
280 args[0] = node_str;
281 Dictionary dict = new Dictionary("interface_" + interface_name, lang);
282 String result = dict.get(key, args);
283 if (result == null)
284 { // not found
285 //if not found, search a separate subdirectory named by the interface name
286 String sep_interface_dir = interface_name + File.separatorChar + lang + File.separatorChar + "interface";
287 dict = new Dictionary(sep_interface_dir, lang);
288 result = dict.get(key, args);
289 if (result != null)
290 {
291 return result;
292 }
293 }
294
295 if (result == null && !interface_name.equals("default"))
296 { // not found, try the default interface
297 dict = new Dictionary("interface_default", lang);
298 result = dict.get(key, args);
299 }
300
301 if (result == null)
302 { // not found
303 return "_" + key + "_";
304 }
305
306 return result;
307 }
308
309 public static String getInterfaceTextWithDOM(String interface_name, String lang, String key, Node arg1_node, Node arg2_node)
310 {
311 String[] args = new String[2];
312
313 String node_str = XMLConverter.getString(arg1_node);
314 args[0] = node_str;
315 node_str = XMLConverter.getString(arg2_node);
316 args[1] = node_str;
317 Dictionary dict = new Dictionary("interface_" + interface_name, lang);
318 String result = dict.get(key, args);
319 if (result == null)
320 { // not found
321 //if not found, search a separate subdirectory named by the interface name
322 String sep_interface_dir = interface_name + File.separatorChar + lang + File.separatorChar + "interface";
323 dict = new Dictionary(sep_interface_dir, lang);
324 result = dict.get(key, args);
325 if (result != null)
326 {
327 return result;
328 }
329 }
330
331 if (result == null && !interface_name.equals("default"))
332 { // not found, try the default interface
333 dict = new Dictionary("interface_default", lang);
334 result = dict.get(key, args);
335 }
336
337 if (result == null)
338 { // not found
339 return "_" + key + "_";
340 }
341
342 return result;
343 }
344
345 public static Node getCollectionText(String collection, String site_name, String lang, String key)
346 {
347 return getCollectionTextWithArgs(collection, site_name, lang, key, null);
348 }
349
350 public static Node getCollectionText(String collection, String site_name, String lang, String key, String args_str)
351 {
352
353 String[] args = null;
354 if (args_str != null && !args_str.equals(""))
355 {
356 args = StringUtils.split(args_str, ";");
357 }
358
359 return getCollectionTextWithArgs(collection, site_name, lang, key, args);
360 }
361
362 // xslt didn't like calling the function with Node varargs, so have this hack for now
363 public static Node getCollectionTextWithDOM(String collection, String site_name, String lang, String key, Node n1)
364 {
365 return getCollectionTextWithDOMMulti(collection, site_name, lang, key, n1);
366 }
367
368 public static Node getCollectionTextWithDOM(String collection, String site_name, String lang, String key, Node n1, Node n2)
369 {
370 return getCollectionTextWithDOMMulti(collection, site_name, lang, key, n1, n2);
371 }
372
373 public static Node getCollectionTextWithDOM(String collection, String site_name, String lang, String key, Node n1, Node n2, Node n3)
374 {
375 return getCollectionTextWithDOMMulti(collection, site_name, lang, key, n1, n2, n3);
376 }
377
378 public static Node getCollectionTextWithDOM(String collection, String site_name, String lang, String key, Node n1, Node n2, Node n3, Node n4)
379 {
380 return getCollectionTextWithDOMMulti(collection, site_name, lang, key, n1, n2, n3, n4);
381 }
382
383 public static Node getCollectionTextWithDOMMulti(String collection, String site_name, String lang, String key, Node... nodes)
384 {
385 int num_nodes = nodes.length;
386 String[] args = null;
387 if (num_nodes != 0)
388 {
389 args = new String[num_nodes];
390
391 for (int i = 0; i < num_nodes; i++)
392 {
393 String node_str = XMLConverter.getString(nodes[i]);
394 args[i] = node_str;
395 }
396 }
397 return getCollectionTextWithArgs(collection, site_name, lang, key, args);
398 }
399
400 public static Node getCollectionTextWithArgs(String collection, String site_name, String lang, String key, String[] args)
401 {
402 try
403 {
404 DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
405
406 CollectionClassLoader class_loader = new CollectionClassLoader(XSLTUtil.class.getClassLoader(), GSFile.siteHome(GlobalProperties.getGSDL3Home(), site_name), collection);
407 Dictionary dict = new Dictionary(collection, lang, class_loader);
408 String result = dict.get(key, args);
409 if (result != null)
410 {
411 return docBuilder.parse(new ByteArrayInputStream(("<fragment>" + result + "</fragment>").getBytes("UTF-8"))).getDocumentElement();
412 }
413 return docBuilder.parse(new ByteArrayInputStream(("<fragment>" + "text:" + collection + ":" + key + "</fragment>").getBytes())).getDocumentElement();
414 }
415 catch (Exception ex)
416 {
417 return null;
418 }
419 }
420
421 public static boolean isImage(String mimetype)
422 {
423 if (mimetype.startsWith("image/"))
424 {
425 return true;
426 }
427 return false;
428 }
429
430 // formatting /preprocessing functions
431 // some require a language, so we'll have a language param for all
432 public static String toLower(String orig, String lang)
433 {
434 return orig.toLowerCase();
435 }
436
437 public static String toUpper(String orig, String lang)
438 {
439 return orig.toUpperCase();
440 }
441
442 public static String tidyWhitespace(String original, String lang)
443 {
444
445 if (original == null || original.equals(""))
446 {
447 return original;
448 }
449 String new_s = original.replaceAll("\\s+", " ");
450 return new_s;
451 }
452
453 public static String stripWhitespace(String original, String lang)
454 {
455
456 if (original == null || original.equals(""))
457 {
458 return original;
459 }
460 String new_s = original.replaceAll("\\s+", "");
461 return new_s;
462 }
463
464 public static byte[] toUTF8(String orig, String lang)
465 {
466 try
467 {
468 byte[] utf8 = orig.getBytes("UTF-8");
469 return utf8;
470 }
471 catch (Exception e)
472 {
473 logger.error("unsupported encoding");
474 return orig.getBytes();
475 }
476 }
477
478 public static String formatDate(String date, String lang)
479 {
480 String in_pattern = "yyyyMMdd";
481 String out_pattern = "dd MMMM yyyy";
482 if (date.length() == 6)
483 {
484 in_pattern = "yyyyMM";
485 }
486
487 SimpleDateFormat formatter = new SimpleDateFormat(in_pattern, new Locale(lang));
488 try
489 {
490 Date d = formatter.parse(date);
491 formatter.applyPattern(out_pattern);
492 String new_date = formatter.format(d);
493 return new_date;
494 }
495 catch (Exception e)
496 {
497 return date;
498 }
499
500 }
501
502 public static String getDetailFromDate(String date, String detail, String lang)
503 {
504 String in_pattern = "yyyyMMdd";
505 if (date.length() == 6)
506 {
507 in_pattern = "yyyyMM";
508 }
509
510 SimpleDateFormat formatter = new SimpleDateFormat(in_pattern, new Locale(lang));
511 try
512 {
513 Date d = formatter.parse(date);
514 if (detail.toLowerCase().equals("day"))
515 {
516 formatter.applyPattern("dd");
517 }
518 else if (detail.toLowerCase().equals("month"))
519 {
520 formatter.applyPattern("MMMM");
521 }
522 else if (detail.toLowerCase().equals("year"))
523 {
524 formatter.applyPattern("yyyy");
525 }
526 else
527 {
528 return "";
529 }
530 return formatter.format(d);
531 }
532 catch (Exception ex)
533 {
534 return "";
535 }
536 }
537
538 public static String formatLanguage(String display_lang, String lang)
539 {
540
541 return new Locale(display_lang).getDisplayLanguage(new Locale(lang));
542 }
543
544 public static String cgiSafe(String original, String lang)
545 {
546
547 original = original.replace('&', ' ');
548 original = original.replaceAll(" ", "%20");
549 return original;
550 }
551
552 public static String formatBigNumber(String num, String lang)
553 {
554
555 String num_str = num;
556 char[] num_chars = num_str.toCharArray();
557 String zero_str = "";
558 String formatted_str = "";
559
560 for (int i = num_chars.length - 4; i >= 0; i--)
561 {
562 zero_str += '0';
563 }
564
565 String sig_str = "";
566 for (int i = 0; i < 3 && i < num_chars.length; i++)
567 {
568 sig_str = sig_str + num_chars[i];
569 if (i == 1 && i + 1 < num_chars.length)
570 {
571 sig_str = sig_str + ".";
572 }
573 }
574
575 int sig_int = Math.round(Float.parseFloat(sig_str));
576 String new_sig_str = sig_int + "";
577 if (sig_str.length() > 2)
578 {
579 new_sig_str = sig_int + "0";
580 }
581
582 char[] final_chars = (new_sig_str + zero_str).toCharArray();
583 int count = 1;
584 for (int i = final_chars.length - 1; i >= 0; i--)
585 {
586 formatted_str = final_chars[i] + formatted_str;
587 if (count == 3 && i != 0)
588 {
589 formatted_str = "," + formatted_str;
590 count = 1;
591 }
592 else
593 {
594 count++;
595 }
596 }
597 return formatted_str;
598 }
599
600 public static String hashToSectionId(String hashString)
601 {
602 if (hashString == null || hashString.length() == 0)
603 {
604 return "";
605 }
606
607 int firstDotIndex = hashString.indexOf(".");
608 if (firstDotIndex == -1)
609 {
610 return "";
611 }
612
613 String sectionString = hashString.substring(firstDotIndex + 1);
614
615 return sectionString;
616 }
617
618 public static String hashToDepthClass(String hashString)
619 {
620 if (hashString == null || hashString.length() == 0)
621 {
622 return "";
623 }
624
625 String sectionString = hashToSectionId(hashString);
626
627 int count = sectionString.split("\\.").length;
628
629 if (sectionString.equals(""))
630 {
631 return "sectionHeaderDepthTitle";
632 }
633 else
634 {
635 return "sectionHeaderDepth" + count;
636 }
637 }
638
639 public static String escapeNewLines(String str)
640 {
641 if (str == null || str.length() < 1)
642 {
643 return null;
644 }
645 return str.replace("\n", "\\\n");
646 }
647
648 public static String escapeQuotes(String str)
649 {
650 if (str == null || str.length() < 1)
651 {
652 return null;
653 }
654 return str.replace("\"", "\\\"");
655 }
656
657 public static String escapeNewLinesAndQuotes(String str)
658 {
659 if (str == null || str.length() < 1)
660 {
661 return null;
662 }
663 return escapeNewLines(escapeQuotes(str));
664 }
665
666 public static String getGlobalProperty(String name)
667 {
668 return GlobalProperties.getProperty(name);
669 }
670
671 public static void clearMetadataStorage()
672 {
673 _foundTableValues.clear();
674 }
675
676 public static boolean checkMetadataNotDuplicate(String name, String value)
677 {
678 if (_foundTableValues.containsKey(name))
679 {
680 for (String mapValue : _foundTableValues.get(name))
681 {
682 if (mapValue.equals(value))
683 {
684 return false;
685 }
686 }
687 _foundTableValues.get(name).add(value);
688 return true;
689 }
690
691 ArrayList<String> newList = new ArrayList<String>();
692 newList.add(value);
693
694 _foundTableValues.put(name, newList);
695
696 return true;
697 }
698
699 public static String reCAPTCHAimage(String publicKey, String privateKey)
700 {
701 ReCaptcha c = ReCaptchaFactory.newReCaptcha(publicKey, privateKey, false);
702 return c.createRecaptchaHtml(null, null);
703 }
704
705 public static String getInterfaceStringsAsJavascript(String interface_name, String lang, String prefix)
706 {
707 String prependToPrefix = "gs.text";
708 return XSLTUtil.getInterfaceStringsAsJavascript(interface_name, lang, prefix, prependToPrefix);
709 }
710
711 // generates javascript: 2 arrays are declared and populated with strings that declare variables and assign their values
712 // to be strings loaded from the interface_name.properties file for the language.
713 public static String getInterfaceStringsAsJavascript(String interface_name, String lang, String prefix, String prependToPrefix)
714 {
715 // 1. Generating Javascript of the form:
716 // if(!gs.text) { gs.text = new Array(); }
717 // if(!gs.text.dse) { gs.text.dse = new Array(); }
718 StringBuffer outputStr = new StringBuffer();
719 outputStr.append("if(!gs.text) { ");
720 outputStr.append(prependToPrefix + " = new Array(); ");
721 outputStr.append("}\n");
722 outputStr.append("if(!gs.text." + prefix + ") { ");
723 outputStr.append(prependToPrefix + "." + prefix + " = new Array(); ");
724 outputStr.append("}\n");
725
726 int foundCount = 0;
727
728 for (String dictName : new String[] { "interface_" + interface_name, "interface_default", "interface_default2" })
729 {
730 Dictionary dict = new Dictionary(dictName, lang);
731 Enumeration keys = dict.getKeys();
732 if (keys == null)
733 {
734 continue;
735 }
736
737 // Get all properties in the language-specific dictionary with the given key prefix
738 // Create Javascript strings of the form:
739 // prependToPrefix.key= "value";\n
740 while (keys.hasMoreElements())
741 {
742 String key = (String) keys.nextElement();
743 if (key.startsWith(prefix))
744 {
745 String value = getInterfaceText(interface_name, dictName, lang, key, null);
746
747 outputStr.append(prependToPrefix);
748 outputStr.append(".");
749 outputStr.append(key);
750 outputStr.append("=\"");
751 outputStr.append(value);
752 outputStr.append("\";\n");
753 }
754 }
755
756 if (foundCount > 0)
757 {
758 break;
759 }
760 }
761
762 return outputStr.toString();
763 }
764
765 public static String xmlNodeToString(Node node)
766 {
767 return GSXML.xmlNodeToString(node);
768 }
769
770 // Test from cmdline with:
771 // java -classpath /research/ak19/gs3-svn/web/WEB-INF/lib/gsdl3.jar:/research/ak19/gs3-svn/web/WEB-INF/lib/log4j-1.2.8.jar:/research/ak19/gs3-svn/web/WEB-INF/classes/ org.greenstone.gsdl3.util.XSLTUtil
772 public static void main(String args[])
773 {
774 System.out.println("\n@@@@@\n" + XSLTUtil.getInterfaceStringsAsJavascript("default", "en", "dse", "gs.text") + "@@@@@\n");
775 }
776}
Note: See TracBrowser for help on using the repository browser.