1 package org.kuali.ole.utility.callnumber;
2
3 /**
4 * Created with IntelliJ IDEA.
5 * User: ?
6 * Date: 19/2/13
7 * Time: 9:23 PM
8 * To change this template use File | Settings | File Templates.
9 */
10
11 import org.marc4j.marc.DataField;
12 import org.marc4j.marc.Record;
13 import org.marc4j.marc.Subfield;
14 import org.marc4j.marc.VariableField;
15 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory;
17
18 import java.io.*;
19 import java.net.MalformedURLException;
20 import java.net.URL;
21 import java.text.DecimalFormat;
22 import java.text.SimpleDateFormat;
23 import java.util.*;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26
27 /**
28 * General utility functions for solrmarc
29 *
30 * @author Wayne Graham
31 * @version $Id: Utils.java 1612 2012-03-21 17:39:16Z rh9ec@virginia.edu $
32 */
33
34 public final class Utils {
35
36 private final static Pattern FOUR_DIGIT_PATTERN_BRACES = Pattern.compile("\\[[12]\\d{3,3}\\]");
37 private final static Pattern FOUR_DIGIT_PATTERN_ONE_BRACE = Pattern.compile("\\[[12]\\d{3,3}");
38 private final static Pattern FOUR_DIGIT_PATTERN_STARTING_WITH_1_2 = Pattern.compile("(20|19|18|17|16|15)[0-9][0-9]");
39 private final static Pattern FOUR_DIGIT_PATTERN_OTHER_1 = Pattern.compile("l\\d{3,3}");
40 private final static Pattern FOUR_DIGIT_PATTERN_OTHER_2 = Pattern.compile("\\[19\\]\\d{2,2}");
41 private final static Pattern FOUR_DIGIT_PATTERN_OTHER_3 = Pattern.compile("(20|19|18|17|16|15)[0-9][-?0-9]");
42 private final static Pattern FOUR_DIGIT_PATTERN_OTHER_4 = Pattern.compile("i.e. (20|19|18|17|16|15)[0-9][0-9]");
43 private final static Pattern BC_DATE_PATTERN = Pattern.compile("[0-9]+ [Bb][.]?[Cc][.]?");
44 private final static Pattern FOUR_DIGIT_PATTERN = Pattern.compile("\\d{4,4}");
45 private static Matcher matcher;
46 private static Matcher matcher_braces;
47 private static Matcher matcher_one_brace;
48 private static Matcher matcher_start_with_1_2;
49 private static Matcher matcher_l_plus_three_digits;
50 private static Matcher matcher_bracket_19_plus_two_digits;
51 private static Matcher matcher_ie_date;
52 private static Matcher matcher_bc_date;
53 private static Matcher matcher_three_digits_plus_unk;
54 private final static DecimalFormat timeFormat = new DecimalFormat("00.00");
55 protected static Logger logger = LoggerFactory.getLogger(Utils.class);
56
57 /**
58 * Default Constructor
59 * It's private, so it can't be instantiated by other objects
60 */
61 private Utils() {
62 }
63
64 /**
65 * Check first for a particular property in the System Properties, so that the -Dprop="value" command line arg
66 * mechanism can be used to override values defined in the passed in property file. This is especially useful
67 * for defining the marc.source property to define which file to operate on, in a shell script loop.
68 *
69 * @param props - property set in which to look.
70 * @param propname - name of the property to lookup.
71 * @returns String - value stored for that property (or null if it doesn't exist)
72 */
73 public static String getProperty(Properties props, String propname) {
74 return getProperty(props, propname, null);
75 }
76
77 /**
78 * Check first for a particular property in the System Properties, so that the -Dprop="value" command line arg
79 * mechanism can be used to override values defined in the passed in property file. This is especially useful
80 * for defining the marc.source property to define which file to operate on, in a shell script loop.
81 *
82 * @param props - property set in which to look.
83 * @param propname - name of the property to lookup.
84 * @param defVal - the default value to use if property is not defined
85 * @returns String - value stored for that property (or the if it doesn't exist)
86 */
87 public static String getProperty(Properties props, String propname, String defVal) {
88 String prop;
89 if ((prop = System.getProperty(propname)) != null) {
90 return (prop);
91 }
92 if (props != null && (prop = props.getProperty(propname)) != null) {
93 return (prop);
94 }
95 return defVal;
96 }
97
98 /**
99 * load a properties file into a Properties object
100 *
101 * @param propertyPaths the directories to search for the properties file
102 * @param propertyFileName name of the sought properties file
103 * @return Properties object
104 */
105 public static Properties loadProperties(String propertyPaths[], String propertyFileName) {
106 return (loadProperties(propertyPaths, propertyFileName, false, null));
107 }
108
109 /**
110 * load a properties file into a Properties object
111 *
112 * @param propertyPaths the directories to search for the properties file
113 * @param propertyFileName name of the sought properties file
114 * @return Properties object
115 */
116 public static Properties loadProperties(String propertyPaths[], String propertyFileName, boolean showName) {
117 return (loadProperties(propertyPaths, propertyFileName, showName, null));
118 }
119
120 /**
121 * load a properties file into a Properties object
122 *
123 * @param fullFilenameURLStr String representation of url to properties file whether it is in a local file or a resource
124 * @return Properties object
125 */
126 public static Properties loadProperties(String fullFilenameURLStr) {
127 InputStream in = getPropertyFileInputStream(fullFilenameURLStr);
128 String errmsg = "Fatal error: Unable to find specified properties file: " + fullFilenameURLStr;
129
130 // load the properties
131 Properties props = new Properties();
132 try {
133 if (fullFilenameURLStr.endsWith(".xml") || fullFilenameURLStr.endsWith(".XML")) {
134 props.loadFromXML(in);
135 } else {
136 props.load(in);
137 }
138 in.close();
139 } catch (IOException e) {
140 throw new IllegalArgumentException(errmsg);
141 }
142 return props;
143 }
144
145 /**
146 * load a properties file into a Properties object
147 *
148 * @param propertyPaths the directories to search for the properties file
149 * @param propertyFileName name of the sought properties file
150 * @param showName whether the name of the file/resource being read should be shown.
151 * @return Properties object
152 */
153 public static Properties loadProperties(String propertyPaths[], String propertyFileName, boolean showName, String filenameProperty) {
154 String inputStreamSource[] = new String[]{null};
155 InputStream in = getPropertyFileInputStream(propertyPaths, propertyFileName, showName, inputStreamSource);
156 String errmsg = "Fatal error: Unable to find specified properties file: " + propertyFileName;
157
158 // load the properties
159 Properties props = new Properties();
160 try {
161 if (propertyFileName.endsWith(".xml") || propertyFileName.endsWith(".XML")) {
162 props.loadFromXML(in);
163 } else {
164 props.load(in);
165 }
166 in.close();
167 if (filenameProperty != null && inputStreamSource[0] != null) {
168 File tmpFile = new File(inputStreamSource[0]);
169
170 props.setProperty(filenameProperty, tmpFile.getParent());
171 }
172 } catch (IOException e) {
173 throw new IllegalArgumentException(errmsg);
174 }
175 return props;
176 }
177
178 public static InputStream getPropertyFileInputStream(String[] propertyPaths, String propertyFileName) {
179 return (getPropertyFileInputStream(propertyPaths, propertyFileName, false));
180 }
181
182 public static InputStream getPropertyFileInputStream(String[] propertyPaths, String propertyFileName, boolean showName) {
183 return (getPropertyFileInputStream(propertyPaths, propertyFileName, false, null));
184 }
185
186 public static InputStream getPropertyFileInputStream(String propertyFileURLStr) {
187 InputStream in = null;
188 String errmsg = "Fatal error: Unable to open specified properties file: " + propertyFileURLStr;
189 try {
190 URL url = new URL(propertyFileURLStr);
191 in = url.openStream();
192 } catch (IOException e) {
193 throw new IllegalArgumentException(errmsg);
194 }
195
196 return (in);
197 }
198
199 public static InputStream getPropertyFileInputStream(String[] propertyPaths, String propertyFileName, boolean showName, String inputSource[]) {
200 InputStream in = null;
201 String fullPropertyFileURLStr = getPropertyFileAbsoluteURL(propertyPaths, propertyFileName, showName, inputSource);
202 return (getPropertyFileInputStream(fullPropertyFileURLStr));
203 }
204
205 // String verboseStr = System.getProperty("marc.test.verbose");
206 // boolean verbose = (verboseStr != null && verboseStr.equalsIgnoreCase("true"));
207 // String lookedIn = "";
208 // if (propertyPaths != null)
209 // {
210 // File propertyFile = new File(propertyFileName);
211 // int pathCnt = 0;
212 // do
213 // {
214 // if (propertyFile.exists() && propertyFile.isFile() && propertyFile.canRead())
215 // {
216 // try
217 // {
218 // in = new FileInputStream(propertyFile);
219 // if (inputSource != null && inputSource.length >= 1)
220 // {
221 // inputSource[0] = propertyFile.getAbsolutePath();
222 // }
223 // if (showName)
224 // logger.info("Opening file: "+ propertyFile.getAbsolutePath());
225 // else
226 // logger.debug("Opening file: "+ propertyFile.getAbsolutePath());
227 // }
228 // catch (FileNotFoundException e)
229 // {
230 // // simply eat this exception since we should only try to open the file if we previously
231 // // determined that the file exists and is readable.
232 // }
233 // break; // we found it!
234 // }
235 // if (verbose) lookedIn = lookedIn + propertyFile.getAbsolutePath() + "\n";
236 // if (propertyPaths != null && pathCnt < propertyPaths.length)
237 // {
238 // propertyFile = new File(propertyPaths[pathCnt], propertyFileName);
239 // }
240 // pathCnt++;
241 // } while (propertyPaths != null && pathCnt <= propertyPaths.length);
242 // }
243 // // if we didn't find it as a file, look for it as a URL
244 // String errmsg = "Fatal error: Unable to find specified properties file: " + propertyFileName;
245 // if (verbose) errmsg = errmsg + "\n Looked in: "+ lookedIn;
246 // if (in == null)
247 // {
248 // Utils utilObj = new Utils();
249 // URL url = utilObj.getClass().getClassLoader().getResource(propertyFileName);
250 // if (url == null)
251 // url = utilObj.getClass().getResource("/" + propertyFileName);
252 // if (url == null)
253 // {
254 // logger.error(errmsg);
255 // throw new IllegalArgumentException(errmsg);
256 // }
257 // if (showName)
258 // logger.info("Opening resource via URL: "+ url.toString());
259 // else
260 // logger.debug("Opening resource via URL: "+ url.toString());
261 //
262 ///*
263 // if (url == null)
264 // url = utilObj.getClass().getClassLoader().getResource(propertyPath + "/" + propertyFileName);
265 // if (url == null)
266 // url = utilObj.getClass().getResource("/" + propertyPath + "/" + propertyFileName);
267 //*/
268 // if (url != null)
269 // {
270 // try
271 // {
272 // in = url.openStream();
273 // }
274 // catch (IOException e)
275 // {
276 // throw new IllegalArgumentException(errmsg);
277 // }
278 // }
279 // }
280 // return(in);
281 // }
282
283 public static String getPropertyFileAbsoluteURL(String[] propertyPaths, String propertyFileName, boolean showName, String inputSource[]) {
284 InputStream in = null;
285 // look for properties file in paths
286 String verboseStr = System.getProperty("marc.test.verbose");
287 boolean verbose = (verboseStr != null && verboseStr.equalsIgnoreCase("true"));
288 String lookedIn = "";
289 String fullPathName = null;
290 if (propertyPaths != null) {
291 File propertyFile = new File(propertyFileName);
292 int pathCnt = 0;
293 do {
294 if (propertyFile.exists() && propertyFile.isFile() && propertyFile.canRead()) {
295 try {
296 fullPathName = propertyFile.toURI().toURL().toExternalForm();
297 if (inputSource != null && inputSource.length >= 1) {
298 inputSource[0] = propertyFile.getAbsolutePath();
299 }
300 } catch (MalformedURLException e) {
301 // TODO Auto-generated catch block
302 e.printStackTrace();
303 }
304 if (showName)
305 logger.info("Opening file: " + propertyFile.getAbsolutePath());
306 else
307 logger.debug("Opening file: " + propertyFile.getAbsolutePath());
308 break; // we found it!
309 }
310 if (verbose) lookedIn = lookedIn + propertyFile.getAbsolutePath() + "\n";
311 if (propertyPaths != null && pathCnt < propertyPaths.length) {
312 propertyFile = new File(propertyPaths[pathCnt], propertyFileName);
313 }
314 pathCnt++;
315 } while (propertyPaths != null && pathCnt <= propertyPaths.length);
316 }
317 // if we didn't find it as a file, look for it as a URL
318 String errmsg = "Fatal error: Unable to find specified properties file: " + propertyFileName;
319 if (verbose) errmsg = errmsg + "\n Looked in: " + lookedIn;
320 if (fullPathName == null) {
321 Utils utilObj = new Utils();
322 URL url = utilObj.getClass().getClassLoader().getResource(propertyFileName);
323 if (url == null)
324 url = utilObj.getClass().getResource("/" + propertyFileName);
325 if (url == null) {
326 logger.error(errmsg);
327 throw new IllegalArgumentException(errmsg);
328 }
329 if (showName)
330 logger.info("Opening resource via URL: " + url.toString());
331 else
332 logger.debug("Opening resource via URL: " + url.toString());
333
334 /*
335 if (url == null)
336 url = utilObj.getClass().getClassLoader().getResource(propertyPath + "/" + propertyFileName);
337 if (url == null)
338 url = utilObj.getClass().getResource("/" + propertyPath + "/" + propertyFileName);
339 */
340 fullPathName = url.toExternalForm();
341 }
342 return (fullPathName);
343 }
344
345
346 /**
347 * Takes an InputStream, reads the entire contents into a String
348 *
349 * @param stream - the stream to read in.
350 * @return String containing entire contents of stream.
351 */
352 public static String readStreamIntoString(InputStream stream) throws IOException {
353 Reader in = new BufferedReader(new InputStreamReader(stream));
354
355 StringBuilder sb = new StringBuilder();
356 char[] chars = new char[4096];
357 int length;
358
359 while ((length = in.read(chars)) > 0) {
360 sb.append(chars, 0, length);
361 }
362
363 return sb.toString();
364 }
365
366
367 /**
368 * Cleans non-digits from a String
369 *
370 * @param date String to parse
371 * @return Numeric part of date String (or null)
372 */
373 public static String cleanDate(final String date) {
374 matcher_braces = FOUR_DIGIT_PATTERN_BRACES.matcher(date);
375 matcher_one_brace = FOUR_DIGIT_PATTERN_ONE_BRACE.matcher(date);
376 matcher_start_with_1_2 = FOUR_DIGIT_PATTERN_STARTING_WITH_1_2.matcher(date);
377 matcher_l_plus_three_digits = FOUR_DIGIT_PATTERN_OTHER_1.matcher(date);
378 matcher_bracket_19_plus_two_digits = FOUR_DIGIT_PATTERN_OTHER_2.matcher(date);
379 matcher_three_digits_plus_unk = FOUR_DIGIT_PATTERN_OTHER_3.matcher(date);
380 matcher_ie_date = FOUR_DIGIT_PATTERN_OTHER_4.matcher(date);
381 matcher = FOUR_DIGIT_PATTERN.matcher(date);
382 matcher_bc_date = BC_DATE_PATTERN.matcher(date);
383
384 String cleanDate = null; // raises DD-anomaly
385
386 if (matcher_braces.find()) {
387 cleanDate = matcher_braces.group();
388 cleanDate = Utils.removeOuterBrackets(cleanDate);
389 if (matcher.find()) {
390 String tmp = matcher.group();
391 if (!tmp.equals(cleanDate)) {
392 tmp = "" + tmp;
393 }
394 }
395 } else if (matcher_ie_date.find()) {
396 cleanDate = matcher_ie_date.group().replaceAll("i.e. ", "");
397 } else if (matcher_one_brace.find()) {
398 cleanDate = matcher_one_brace.group();
399 cleanDate = Utils.removeOuterBrackets(cleanDate);
400 if (matcher.find()) {
401 String tmp = matcher.group();
402 if (!tmp.equals(cleanDate)) {
403 tmp = "" + tmp;
404 }
405 }
406 } else if (matcher_bc_date.find()) {
407 cleanDate = null;
408 } else if (matcher_start_with_1_2.find()) {
409 cleanDate = matcher_start_with_1_2.group();
410 } else if (matcher_l_plus_three_digits.find()) {
411 cleanDate = matcher_l_plus_three_digits.group().replaceAll("l", "1");
412 } else if (matcher_bracket_19_plus_two_digits.find()) {
413 cleanDate = matcher_bracket_19_plus_two_digits.group().replaceAll("\\[", "").replaceAll("\\]", "");
414 } else if (matcher_three_digits_plus_unk.find()) {
415 cleanDate = matcher_three_digits_plus_unk.group().replaceAll("[-?]", "0");
416 }
417 if (cleanDate != null) {
418 Calendar calendar = Calendar.getInstance();
419 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");
420 String thisYear = dateFormat.format(calendar.getTime());
421 try {
422 if (Integer.parseInt(cleanDate) > Integer.parseInt(thisYear) + 1)
423 cleanDate = null;
424 } catch (NumberFormatException nfe) {
425 cleanDate = null;
426 }
427 }
428 if (cleanDate != null) {
429 logger.debug("Date : " + date + " mapped to : " + cleanDate);
430 } else {
431 logger.debug("No Date match: " + date);
432 }
433 return cleanDate;
434 }
435
436 /**
437 * Removes trailing characters (space, comma, slash, semicolon, colon),
438 * trailing period if it is preceded by at least three letters,
439 * and single square bracket characters if they are the start and/or end
440 * chars of the cleaned string
441 *
442 * @param origStr String to clean
443 * @return cleaned string
444 */
445 public static String cleanData(String origStr) {
446 String currResult = origStr;
447 String prevResult;
448 do {
449 prevResult = currResult;
450 currResult = currResult.trim();
451
452 currResult = currResult.replaceAll(" *([,/;:])$", "");
453
454 // trailing period removed in certain circumstances
455 if (currResult.endsWith(".")) {
456 if (currResult.matches(".*[JS]r\\.$")) {
457 // dont strip period off of Jr. or Sr.
458 } else if (currResult.matches(".*\\w\\w\\.$")) {
459 currResult = currResult.substring(0, currResult.length() - 1);
460 } else if (currResult.matches(".*\\p{L}\\p{L}\\.$")) {
461 currResult = currResult.substring(0, currResult.length() - 1);
462 } else if (currResult.matches(".*\\w\\p{InCombiningDiacriticalMarks}?\\w\\p{InCombiningDiacriticalMarks}?\\.$")) {
463 currResult = currResult.substring(0, currResult.length() - 1);
464 } else if (currResult.matches(".*\\p{Punct}\\.$")) {
465 currResult = currResult.substring(0, currResult.length() - 1);
466 }
467 }
468
469 currResult = removeOuterBrackets(currResult);
470
471 if (currResult.length() == 0)
472 return currResult;
473
474 } while (!currResult.equals(prevResult));
475
476 // if (!currResult.equals(origStr))
477 // System.out.println(origStr + " -> "+ currResult);
478
479 return currResult;
480 }
481
482 /**
483 * Call cleanData on an entire set of Strings has a side effect
484 * of deleting entries that are identical when they are cleaned.
485 *
486 * @param values - the set to clean
487 * @return Set<String> - the "same" set with all of its entries cleaned.
488 */
489 private static Set<String> cleanData(Set<String> values) {
490 Set<String> result = new LinkedHashSet<String>();
491 for (String entry : values) {
492 String cleaned = cleanData(entry);
493 result.add(cleaned);
494 }
495 return (result);
496 }
497
498
499 /**
500 * Repeatedly removes trailing characters indicated in regular expression,
501 * PLUS trailing period if it is preceded by its regular expression
502 *
503 * @param origStr String to clean
504 * @param trailingCharsRegEx a regular expression of trailing chars to be
505 * removed (see java Pattern class). Note that the regular expression
506 * should NOT have '$' at the end.
507 * (e.g. " *[,/;:]" replaces any commas, slashes, semicolons or colons
508 * at the end of the string, and these chars may optionally be preceded
509 * by a space)
510 * @param charsB4periodRegEx a regular expression that must immediately
511 * precede a trailing period IN ORDER FOR THE PERIOD TO BE REMOVED.
512 * Note that the regular expression will NOT have the period or '$' at
513 * the end.
514 * (e.g. "[a-zA-Z]{3,}" means at least three letters must immediately
515 * precede the period for it to be removed.)
516 * @return cleaned string
517 */
518 public static String removeAllTrailingCharAndPeriod(String origStr, String trailingCharsRegEx, String charsB4periodRegEx) {
519 if (origStr == null)
520 return null;
521
522 String currResult = origStr;
523 String prevResult;
524 do {
525 prevResult = currResult;
526 currResult = removeTrailingCharAndPeriod(currResult.trim(), trailingCharsRegEx, charsB4periodRegEx);
527
528 if (currResult.length() == 0)
529 return currResult;
530
531 } while (!currResult.equals(prevResult));
532
533 return currResult;
534 }
535
536 /**
537 * Removes trailing characters indicated in regular expression, PLUS
538 * trailing period if it is preceded by its regular expression.
539 *
540 * @param origStr String to clean
541 * @param trailingCharsRegEx a regular expression of trailing chars to be
542 * removed (see java Pattern class). Note that the regular expression
543 * should NOT have '$' at the end.
544 * (e.g. " *[,/;:]" replaces any commas, slashes, semicolons or colons
545 * at the end of the string, and these chars may optionally be preceded
546 * by a space)
547 * @param charsB4periodRegEx a regular expression that must immediately
548 * precede a trailing period IN ORDER FOR THE PERIOD TO BE REMOVED.
549 * Note that the regular expression will NOT have the period or '$' at
550 * the end.
551 * (e.g. "[a-zA-Z]{3,}" means at least three letters must immediately
552 * precede the period for it to be removed.)
553 * @return cleaned string
554 */
555 public static String removeTrailingCharAndPeriod(String origStr, String trailingCharsRegEx, String charsB4periodRegEx) {
556 if (origStr == null)
557 return null;
558
559 String result = removeTrailingChar(origStr, trailingCharsRegEx);
560
561 result = removeTrailingPeriod(result, charsB4periodRegEx);
562
563 return result;
564 }
565
566 /**
567 * Remove the characters per the regular expression if they are at the end
568 * of the string.
569 *
570 * @param origStr string to be cleaned
571 * @param charsToReplaceRegEx - a regular expression of the trailing string/chars
572 * to be removed e.g. " *([,/;:])" meaning last character is a comma,
573 * slash, semicolon, colon, possibly preceded by one or more spaces.
574 * @return the string with the specified trailing characters removed
575 * @see java.util.regex.Pattern class in java api
576 */
577 public static String removeTrailingChar(String origStr, String charsToReplaceRegEx) {
578 if (origStr == null)
579 return origStr;
580 // get rid of reg ex specified chars at the end of the string
581 return origStr.trim().replaceAll(charsToReplaceRegEx + "$", "");
582 }
583
584 /**
585 * If there is a period at the end of the string, remove the period if it is
586 * immediately preceded by the regular expression
587 *
588 * @param origStr the string to be cleaned
589 * @param charsB4periodRegEx a regular expression that must immediately
590 * precede a trailing period IN ORDER FOR THE PERIOD TO BE REMOVED.
591 * Note that the regular expression will NOT have the period or '$' at
592 * the end.
593 * (e.g. "[a-zA-Z]{3,}" means at least three letters must immediately
594 * precede the period for it to be removed.)
595 * @return the string without a trailing period iff the regular expression
596 * param was found immediately before the trailing period
597 */
598 public static String removeTrailingPeriod(String origStr, String precedingCharsRegEx) {
599 if (origStr == null)
600 return origStr;
601 String result = origStr.trim();
602 if (result.endsWith(".") && result.matches(".*" + precedingCharsRegEx + "\\.$"))
603 result = result.substring(0, result.length() - 1).trim();
604
605 return result;
606 }
607
608
609 /**
610 * Remove single square bracket characters if they are the start and/or end
611 * chars (matched or unmatched) and are the only square bracket chars in
612 * the string.
613 */
614 public static String removeOuterBrackets(String origStr) {
615 if (origStr == null || origStr.length() == 0)
616 return origStr;
617
618 String result = origStr.trim();
619
620 if (result.length() > 0) {
621 boolean openBracketFirst = result.charAt(0) == '[';
622 boolean closeBracketLast = result.endsWith("]");
623 if (openBracketFirst && closeBracketLast &&
624 result.indexOf('[', 1) == -1 &&
625 result.lastIndexOf(']', result.length() - 2) == -1)
626 // only square brackets are at beginning and end
627 result = result.substring(1, result.length() - 1);
628 else if (openBracketFirst && result.indexOf(']') == -1)
629 // starts with '[' but no ']'; remove open bracket
630 result = result.substring(1);
631 else if (closeBracketLast && result.indexOf('[') == -1)
632 // ends with ']' but no '['; remove close bracket
633 result = result.substring(0, result.length() - 1);
634 }
635
636 return result.trim();
637 }
638
639
640 /**
641 * Calculate time from milliseconds
642 *
643 * @param totalTime Time in milliseconds
644 * @return Time in the format mm:ss.ss
645 */
646 public static String calcTime(final long totalTime) {
647 return totalTime / 60000 + ":" + timeFormat.format((totalTime % 60000) / 1000);
648 }
649
650 /**
651 * Test if a String has a numeric equivalent
652 *
653 * @param number String representation of a number
654 * @return True if String is a number; False if it is not
655 */
656 public static boolean isNumber(final String number) {
657 boolean isNumber; // fix for dd-anomaly
658
659 try {
660 Integer.parseInt(number);
661 isNumber = true;
662 } catch (NumberFormatException nfe) {
663 // eat the exception
664 isNumber = false;
665 }
666
667 return isNumber;
668 }
669
670 /**
671 * Remap a field value. If the field value is not present in the map, then:
672 * if "displayRawIfMissing" is a key in the map, then the raw field value
673 * is used.
674 * if "displayRawIfMissing" is not a key in the map, and the allowDefault
675 * param is set to true, then if the map contains "__DEFAULT" as a key,
676 * the value of "__DEFAULT" in the map is used; if allowDefault is true
677 * and there is neither "displayRawIfMissing" nor "__DEFAULT", as a key
678 * in the map, then if the map contains an empty key, the map value of the
679 * empty key is used.
680 * NOTE: If the spec for a field is supposed to contain all matching
681 * values, then the default lookup needs to be done here. If the spec
682 * for a field is only supposed to return the first matching mappable
683 * value, then the default mapping should be done in the calling method
684 *
685 * @param fieldVal - the raw value to be mapped
686 * @param map - the map to be used
687 * @param allowDefault - if "displayRawIfMissing" is not a key in the map,
688 * and this is to true, then if the map contains "__DEFAULT" as a key,
689 * the value of "__DEFAULT" in the map is used.
690 * @return the new value, as determined by the mapping.
691 */
692 public static String remap(String fieldVal, Map<String, String> map, boolean allowDefault) {
693 String result = null;
694
695 if (map.keySet().contains("pattern_0")) {
696 for (int i = 0; i < map.keySet().size(); i++) {
697 String patternStr = map.get("pattern_" + i);
698 String parts[] = patternStr.split("=>");
699 if (containsMatch(fieldVal, parts[0])) {
700 String newVal = parts[1];
701 if (parts[1].contains("$")) {
702 newVal = fieldVal.replaceAll(parts[0], parts[1]);
703 fieldVal = newVal;
704 }
705 result = newVal;
706 }
707 }
708 }
709 if (map.containsKey(fieldVal)) {
710 result = map.get(fieldVal);
711 } else if (map.containsKey("displayRawIfMissing")) {
712 result = fieldVal;
713 } else if (allowDefault && map.containsKey("__DEFAULT")) {
714 result = map.get("__DEFAULT");
715 } else if (allowDefault && map.containsKey("")) {
716 result = map.get("");
717 }
718 if (result == null || result.length() == 0) return null;
719 return result;
720 }
721
722 /**
723 * Remap a set of field values. If a field value is not present in the map,
724 * then:
725 * if "displayRawIfMissing" is a key in the map, then the raw field value
726 * is used.
727 * if "displayRawIfMissing" is not a key in the map, and the allowDefault
728 * param is set to true, then if the map contains "__DEFAULT" as a key,
729 * the value of "__DEFAULT" in the map is used; if allowDefault is true
730 * and there is neither "displayRawIfMissing" nor "__DEFAULT", as a key
731 * in the map, then if the map contains an empty key, the map value of the
732 * empty key is used.
733 * NOTE: If the spec for a field is supposed to contain all matching
734 * values, then the default lookup needs to be done here. If the spec
735 * for a field is only supposed to return the first matching mappable
736 * value, then the default mapping should be done in the calling method
737 *
738 * @param fieldVal - the raw value to be mapped
739 * @param map - the map to be used
740 * @param allowDefault - if "displayRawIfMissing" is not a key in the map,
741 * and this is to true, then if the map contains "__DEFAULT" as a key,
742 * the value of "__DEFAULT" in the map is used.
743 * @return the new value, as determined by the mapping.
744 */
745 public static Set<String> remap(Set<String> set, Map<String, String> map, boolean allowDefault) {
746 if (map == null) return (set);
747 Iterator<String> iter = set.iterator();
748 Set<String> result = new LinkedHashSet<String>();
749
750 while (iter.hasNext()) {
751 String val = iter.next();
752 if (map.keySet().contains("pattern_0")) {
753 String tmpResult = null;
754 for (int i = 0; i < map.keySet().size(); i++) {
755 String patternStr = map.get("pattern_" + i);
756 String parts[] = patternStr.split("=>");
757 if (containsMatch(val, parts[0])) {
758 String newVal = parts[1];
759 if (parts[1].contains("$")) {
760 newVal = val.replaceAll(parts[0], parts[1]);
761 val = newVal;
762 } else {
763 result.add(newVal);
764 }
765 tmpResult = newVal;
766 }
767 }
768 if (tmpResult != null) result.add(tmpResult);
769 } else {
770 String mappedVal = remap(val, map, allowDefault);
771 if (mappedVal != null) {
772 if (mappedVal.contains("|")) {
773 String vals[] = mappedVal.split("[|]");
774 for (String oneVal : vals) {
775 result.add(oneVal);
776 }
777 } else
778 result.add(mappedVal);
779 }
780 }
781 }
782 return result;
783 }
784
785 private static boolean containsMatch(String val, String pattern) {
786 String rep = val.replaceFirst(pattern, "###match###");
787
788 if (!rep.equals(val)) {
789 return true;
790 }
791
792 return false;
793 }
794
795 /**
796 * Test if a set contains a specified pattern
797 *
798 * @param set Set of marc fields to test
799 * @param pattern Regex String pattern to match
800 * @return If the set contains the pattern, return true, else false
801 */
802 public static boolean setItemContains(Set<String> set, String pattern) {
803 if (set.isEmpty()) {
804 return (false);
805 }
806
807 Iterator<String> iter = set.iterator();
808
809 while (iter.hasNext()) {
810 String value = (String) iter.next();
811
812 if (containsMatch(value, pattern)) {
813 return true;
814 }
815
816 }
817 return false;
818 }
819
820 /**
821 * Join two fields together with seperator
822 *
823 * @param set Set of marc fields to join
824 * @param separator Separation character to put between
825 * @return Joined fields
826 */
827 public static String join(Set<String> set, String separator) {
828 Iterator<String> iter = set.iterator();
829 //String result = "";
830 StringBuffer result = new StringBuffer("");
831
832 while (iter.hasNext()) {
833 //result += iter.next();
834 result.append(iter.next());
835 if (iter.hasNext()) {
836 //result += separator;
837 result.append(separator);
838 }
839 }
840
841 return result.toString();
842 }
843
844 public static Set<String> trimNearDuplicates(Set<String> locations) {
845 locations = cleanData(locations);
846 if (locations.size() <= 1) return (locations);
847 Object locArr[] = locations.toArray();
848 int size = locArr.length;
849 for (int i = 0; i < size; i++) {
850 boolean copyStrI = true;
851 for (int j = 0; j < size; j++) {
852 if (i == j) continue;
853 if (locArr[j].toString().contains(locArr[i].toString())) {
854 copyStrI = false;
855 break;
856 }
857 }
858 if (copyStrI == false) locations.remove(locArr[i]);
859 }
860 return locations;
861 }
862
863
864 /**
865 * returns true if the 3 letter language code is for a right to left
866 * language (one written in arabic or hebrew characters)
867 *
868 * @param langcode
869 * @return
870 */
871 public final static boolean isRightToLeftLanguage(String langcode) {
872 if (
873 // arabic characters
874 langcode.equals("ara") || langcode.equals("per") || langcode.equals("urd")
875 ||
876 // hebrew characters
877 langcode.equals("heb") || langcode.equals("yid") || langcode.equals("lad")
878 || langcode.equals("jpr") || langcode.equals("jrb")
879 )
880 return true;
881 else
882 return false;
883 }
884
885
886 /**
887 * return the index within this string of the first occurrence of an open
888 * parenthesis that isn't escaped with a backslash.
889 *
890 * @param str
891 * @return if an unescaped open parenthesis occurs within this object,
892 * return the index of the first open paren; -1 if no unescaped open paren.
893 */
894 public final static int getIxUnescapedOpenParen(String str) {
895 if (str.startsWith("("))
896 return 0;
897 Pattern p = Pattern.compile(".*[^\\\\](\\().*");
898 Matcher m = p.matcher(str);
899 if (m.matches())
900 return m.start(1);
901 else
902 return -1;
903 }
904
905
906 /**
907 * return the index within this string of the first occurrence of a comma
908 * that isn't escaped with a backslash.
909 *
910 * @param str
911 * @return if an unescaped comma occurs within this object, the index of the
912 * first comma; -1 if no unescaped comma.
913 */
914 public final static int getIxUnescapedComma(String str) {
915 if (str.startsWith(","))
916 return 0;
917 Pattern p = Pattern.compile(".*[^\\\\](,).*");
918 Matcher m = p.matcher(str);
919 if (m.matches())
920 return m.start(1);
921 else
922 return -1;
923 }
924
925 /**
926 * Look for Strings in the set, that start with the given prefix. If found,
927 * remove the prefix, trim the result and add it to the returned set of
928 * Strings to be returned.
929 *
930 * @param valueSet
931 * @param prefix
932 * @return set members that had the prefix, but now prefix is removed and
933 * remaining value is trimmed.
934 */
935 public final static Set<String> getPrefixedVals(Set<String> valueSet, String prefix) {
936 Set<String> resultSet = new LinkedHashSet<String>();
937 if (!valueSet.isEmpty()) {
938 Iterator<String> iter = valueSet.iterator();
939 while (iter.hasNext()) {
940 String s = removePrefix((String) iter.next(), prefix);
941 if (s != null) {
942 String value = s.trim();
943 if (value != null && value.length() != 0)
944 resultSet.add(value);
945 }
946 }
947 }
948 return resultSet;
949 }
950
951 /**
952 * remove prefix from the beginning of the value string.
953 */
954 public final static String removePrefix(String value, String prefix) {
955 if (value.startsWith(prefix)) {
956 value = value.substring(prefix.length());
957 if (value != null && value.length() != 0)
958 return value;
959 }
960 return null;
961 }
962
963 /**
964 * returns the valid ISBN(s) from the set of candidate Strings
965 *
966 * @return Set of strings containing valid ISBN numbers
967 */
968 public static Set<String> returnValidISBNs(Set<String> candidates) {
969 // NOTE 1: last digit of ISBN is a check digit and may be "X" (0,1,2,3,4,5,6.7.8.9.X)
970 // NOTE 2: ISBN can be 10 or 13 digits (and may end with X).
971 // NOTE 3: 13 digit ISBN must start with 978 or 979.
972 // NOTE 4: there may be text after the ISBN, which should be removed
973
974 Set<String> isbnSet = new LinkedHashSet<String>();
975
976 Pattern p10 = Pattern.compile("^\\d{9}[\\dX].*");
977 Pattern p13 = Pattern.compile("^(978|979)\\d{9}[X\\d].*");
978 // p13any matches a 13 digit isbn pattern without the correct prefix
979 Pattern p13any = Pattern.compile("^\\d{12}[X\\d].*");
980
981 Iterator<String> iter = candidates.iterator();
982 while (iter.hasNext()) {
983 String value = (String) iter.next().trim();
984 // check we have the right pattern, and remove trailing text
985 if (p13.matcher(value).matches())
986 isbnSet.add(value.substring(0, 13));
987 else if (p10.matcher(value).matches() && !p13any.matcher(value).matches())
988 isbnSet.add(value.substring(0, 10));
989 }
990 return isbnSet;
991 }
992
993
994 /**
995 * For each occurrence of a marc field in the tags list, extract all
996 * subfield data from the field, place it in a single string (individual
997 * subfield data separated by spaces) and add the string to the result set.
998 */
999 @SuppressWarnings("unchecked")
1000 public static final Set<String> getAllSubfields(final Record record, String[] tags) {
1001 Set<String> result = new LinkedHashSet<String>();
1002
1003 List<VariableField> varFlds = record.getVariableFields(tags);
1004 for (VariableField vf : varFlds) {
1005
1006 StringBuffer buffer = new StringBuffer(500);
1007
1008 DataField df = (DataField) vf;
1009 if (df != null) {
1010 List<Subfield> subfields = df.getSubfields();
1011 for (Subfield sf : subfields) {
1012 if (buffer.length() > 0) {
1013 buffer.append(" " + sf.getData());
1014 } else {
1015 buffer.append(sf.getData());
1016 }
1017 }
1018 }
1019 if (buffer.length() > 0)
1020 result.add(buffer.toString());
1021 }
1022
1023 return result;
1024 }
1025
1026 /**
1027 * get the contents of a subfield, rigorously ensuring no NPE
1028 *
1029 * @param df - DataField of interest
1030 * @param code - code of subfield of interest
1031 * @return the contents of the subfield, if it exists; null otherwise
1032 */
1033 public static final String getSubfieldData(DataField df, char code) {
1034 String result = null;
1035 if (df != null) {
1036 Subfield sf = df.getSubfield(code);
1037 if (sf != null && sf.getData() != null) {
1038 result = sf.getData();
1039 }
1040 }
1041 return result;
1042 }
1043
1044 /**
1045 * returns all values of subfield strings of a particular code
1046 * contained in the data field
1047 */
1048 @SuppressWarnings("unchecked")
1049 public static final List<String> getSubfieldStrings(DataField df, char code) {
1050 List<Subfield> listSubcode = df.getSubfields(code);
1051 List<String> vals = new ArrayList(listSubcode.size());
1052 for (Subfield s : listSubcode) {
1053 vals.add(s.getData());
1054 }
1055 return vals;
1056 }
1057
1058
1059 /**
1060 * given a latin letter with a diacritic, return the latin letter without
1061 * the diacritic.
1062 * Shamelessly stolen from UnicodeCharUtil class of UnicodeNormalizeFilter
1063 * by Bob Haschart
1064 */
1065 public static char foldDiacriticLatinChar(char c) {
1066 switch (c) {
1067 case 0x0181:
1068 return (0x0042); // LATIN CAPITAL LETTER B WITH HOOK -> LATIN CAPITAL LETTER B
1069 case 0x0182:
1070 return (0x0042); // LATIN CAPITAL LETTER B WITH TOPBAR -> LATIN CAPITAL LETTER B
1071 case 0x0187:
1072 return (0x0043); // LATIN CAPITAL LETTER C WITH HOOK -> LATIN CAPITAL LETTER C
1073 case 0x0110:
1074 return (0x0044); // LATIN CAPITAL LETTER D WITH STROKE -> LATIN CAPITAL LETTER D
1075 case 0x018A:
1076 return (0x0044); // LATIN CAPITAL LETTER D WITH HOOK -> LATIN CAPITAL LETTER D
1077 case 0x018B:
1078 return (0x0044); // LATIN CAPITAL LETTER D WITH TOPBAR -> LATIN CAPITAL LETTER D
1079 case 0x0191:
1080 return (0x0046); // LATIN CAPITAL LETTER F WITH HOOK -> LATIN CAPITAL LETTER F
1081 case 0x0193:
1082 return (0x0047); // LATIN CAPITAL LETTER G WITH HOOK -> LATIN CAPITAL LETTER G
1083 case 0x01E4:
1084 return (0x0047); // LATIN CAPITAL LETTER G WITH STROKE -> LATIN CAPITAL LETTER G
1085 case 0x0126:
1086 return (0x0048); // LATIN CAPITAL LETTER H WITH STROKE -> LATIN CAPITAL LETTER H
1087 case 0x0197:
1088 return (0x0049); // LATIN CAPITAL LETTER I WITH STROKE -> LATIN CAPITAL LETTER I
1089 case 0x0198:
1090 return (0x004B); // LATIN CAPITAL LETTER K WITH HOOK -> LATIN CAPITAL LETTER K
1091 case 0x0141:
1092 return (0x004C); // LATIN CAPITAL LETTER L WITH STROKE -> LATIN CAPITAL LETTER L
1093 case 0x019D:
1094 return (0x004E); // LATIN CAPITAL LETTER N WITH LEFT HOOK -> LATIN CAPITAL LETTER N
1095 case 0x0220:
1096 return (0x004E); // LATIN CAPITAL LETTER N WITH LONG RIGHT LEG -> LATIN CAPITAL LETTER N
1097 case 0x00D8:
1098 return (0x004F); // LATIN CAPITAL LETTER O WITH STROKE -> LATIN CAPITAL LETTER O
1099 case 0x019F:
1100 return (0x004F); // LATIN CAPITAL LETTER O WITH MIDDLE TILDE -> LATIN CAPITAL LETTER O
1101 case 0x01FE:
1102 return (0x004F); // LATIN CAPITAL LETTER O WITH STROKE AND ACUTE -> LATIN CAPITAL LETTER O
1103 case 0x01A4:
1104 return (0x0050); // LATIN CAPITAL LETTER P WITH HOOK -> LATIN CAPITAL LETTER P
1105 case 0x0166:
1106 return (0x0054); // LATIN CAPITAL LETTER T WITH STROKE -> LATIN CAPITAL LETTER T
1107 case 0x01AC:
1108 return (0x0054); // LATIN CAPITAL LETTER T WITH HOOK -> LATIN CAPITAL LETTER T
1109 case 0x01AE:
1110 return (0x0054); // LATIN CAPITAL LETTER T WITH RETROFLEX HOOK -> LATIN CAPITAL LETTER T
1111 case 0x01B2:
1112 return (0x0056); // LATIN CAPITAL LETTER V WITH HOOK -> LATIN CAPITAL LETTER V
1113 case 0x01B3:
1114 return (0x0059); // LATIN CAPITAL LETTER Y WITH HOOK -> LATIN CAPITAL LETTER Y
1115 case 0x01B5:
1116 return (0x005A); // LATIN CAPITAL LETTER Z WITH STROKE -> LATIN CAPITAL LETTER Z
1117 case 0x0224:
1118 return (0x005A); // LATIN CAPITAL LETTER Z WITH HOOK -> LATIN CAPITAL LETTER Z
1119 case 0x0180:
1120 return (0x0062); // LATIN SMALL LETTER B WITH STROKE -> LATIN SMALL LETTER B
1121 case 0x0183:
1122 return (0x0062); // LATIN SMALL LETTER B WITH TOPBAR -> LATIN SMALL LETTER B
1123 case 0x0253:
1124 return (0x0062); // LATIN SMALL LETTER B WITH HOOK -> LATIN SMALL LETTER B
1125 case 0x0188:
1126 return (0x0063); // LATIN SMALL LETTER C WITH HOOK -> LATIN SMALL LETTER C
1127 case 0x0255:
1128 return (0x0063); // LATIN SMALL LETTER C WITH CURL -> LATIN SMALL LETTER C
1129 case 0x0111:
1130 return (0x0064); // LATIN SMALL LETTER D WITH STROKE -> LATIN SMALL LETTER D
1131 case 0x018C:
1132 return (0x0064); // LATIN SMALL LETTER D WITH TOPBAR -> LATIN SMALL LETTER D
1133 case 0x0221:
1134 return (0x0064); // LATIN SMALL LETTER D WITH CURL -> LATIN SMALL LETTER D
1135 case 0x0256:
1136 return (0x0064); // LATIN SMALL LETTER D WITH TAIL -> LATIN SMALL LETTER D
1137 case 0x0257:
1138 return (0x0064); // LATIN SMALL LETTER D WITH HOOK -> LATIN SMALL LETTER D
1139 case 0x0192:
1140 return (0x0066); // LATIN SMALL LETTER F WITH HOOK -> LATIN SMALL LETTER F
1141 case 0x01E5:
1142 return (0x0067); // LATIN SMALL LETTER G WITH STROKE -> LATIN SMALL LETTER G
1143 case 0x0260:
1144 return (0x0067); // LATIN SMALL LETTER G WITH HOOK -> LATIN SMALL LETTER G
1145 case 0x0127:
1146 return (0x0068); // LATIN SMALL LETTER H WITH STROKE -> LATIN SMALL LETTER H
1147 case 0x0266:
1148 return (0x0068); // LATIN SMALL LETTER H WITH HOOK -> LATIN SMALL LETTER H
1149 case 0x0268:
1150 return (0x0069); // LATIN SMALL LETTER I WITH STROKE -> LATIN SMALL LETTER I
1151 case 0x029D:
1152 return (0x006A); // LATIN SMALL LETTER J WITH CROSSED-TAIL -> LATIN SMALL LETTER J
1153 case 0x0199:
1154 return (0x006B); // LATIN SMALL LETTER K WITH HOOK -> LATIN SMALL LETTER K
1155 case 0x0142:
1156 return (0x006C); // LATIN SMALL LETTER L WITH STROKE -> LATIN SMALL LETTER L
1157 case 0x019A:
1158 return (0x006C); // LATIN SMALL LETTER L WITH BAR -> LATIN SMALL LETTER L
1159 case 0x0234:
1160 return (0x006C); // LATIN SMALL LETTER L WITH CURL -> LATIN SMALL LETTER L
1161 case 0x026B:
1162 return (0x006C); // LATIN SMALL LETTER L WITH MIDDLE TILDE -> LATIN SMALL LETTER L
1163 case 0x026C:
1164 return (0x006C); // LATIN SMALL LETTER L WITH BELT -> LATIN SMALL LETTER L
1165 case 0x026D:
1166 return (0x006C); // LATIN SMALL LETTER L WITH RETROFLEX HOOK -> LATIN SMALL LETTER L
1167 case 0x0271:
1168 return (0x006D); // LATIN SMALL LETTER M WITH HOOK -> LATIN SMALL LETTER M
1169 case 0x019E:
1170 return (0x006E); // LATIN SMALL LETTER N WITH LONG RIGHT LEG -> LATIN SMALL LETTER N
1171 case 0x0235:
1172 return (0x006E); // LATIN SMALL LETTER N WITH CURL -> LATIN SMALL LETTER N
1173 case 0x0272:
1174 return (0x006E); // LATIN SMALL LETTER N WITH LEFT HOOK -> LATIN SMALL LETTER N
1175 case 0x0273:
1176 return (0x006E); // LATIN SMALL LETTER N WITH RETROFLEX HOOK -> LATIN SMALL LETTER N
1177 case 0x00F8:
1178 return (0x006F); // LATIN SMALL LETTER O WITH STROKE -> LATIN SMALL LETTER O
1179 case 0x01FF:
1180 return (0x006F); // LATIN SMALL LETTER O WITH STROKE AND ACUTE -> LATIN SMALL LETTER O
1181 case 0x01A5:
1182 return (0x0070); // LATIN SMALL LETTER P WITH HOOK -> LATIN SMALL LETTER P
1183 case 0x02A0:
1184 return (0x0071); // LATIN SMALL LETTER Q WITH HOOK -> LATIN SMALL LETTER Q
1185 case 0x027C:
1186 return (0x0072); // LATIN SMALL LETTER R WITH LONG LEG -> LATIN SMALL LETTER R
1187 case 0x027D:
1188 return (0x0072); // LATIN SMALL LETTER R WITH TAIL -> LATIN SMALL LETTER R
1189 case 0x0282:
1190 return (0x0073); // LATIN SMALL LETTER S WITH HOOK -> LATIN SMALL LETTER S
1191 case 0x0167:
1192 return (0x0074); // LATIN SMALL LETTER T WITH STROKE -> LATIN SMALL LETTER T
1193 case 0x01AB:
1194 return (0x0074); // LATIN SMALL LETTER T WITH PALATAL HOOK -> LATIN SMALL LETTER T
1195 case 0x01AD:
1196 return (0x0074); // LATIN SMALL LETTER T WITH HOOK -> LATIN SMALL LETTER T
1197 case 0x0236:
1198 return (0x0074); // LATIN SMALL LETTER T WITH CURL -> LATIN SMALL LETTER T
1199 case 0x0288:
1200 return (0x0074); // LATIN SMALL LETTER T WITH RETROFLEX HOOK -> LATIN SMALL LETTER T
1201 case 0x028B:
1202 return (0x0076); // LATIN SMALL LETTER V WITH HOOK -> LATIN SMALL LETTER V
1203 case 0x01B4:
1204 return (0x0079); // LATIN SMALL LETTER Y WITH HOOK -> LATIN SMALL LETTER Y
1205 case 0x01B6:
1206 return (0x007A); // LATIN SMALL LETTER Z WITH STROKE -> LATIN SMALL LETTER Z
1207 case 0x0225:
1208 return (0x007A); // LATIN SMALL LETTER Z WITH HOOK -> LATIN SMALL LETTER Z
1209 case 0x0290:
1210 return (0x007A); // LATIN SMALL LETTER Z WITH RETROFLEX HOOK -> LATIN SMALL LETTER Z
1211 case 0x0291:
1212 return (0x007A); // LATIN SMALL LETTER Z WITH CURL -> LATIN SMALL LETTER Z
1213 default:
1214 return (0x00);
1215 }
1216 }
1217
1218 // @SuppressWarnings("unchecked")
1219 // public static void setLog4jLogLevel(org.apache.log4j.Level newLevel)
1220 // {
1221 // Logger rootLogger = org.apache.log4j.Logger.getRootLogger();
1222 // Enumeration<Logger> enLogger = rootLogger.getLoggerRepository().getCurrentLoggers();
1223 // Logger tmpLogger = null;
1224 // /* If logger is root, then need to loop through all loggers under root
1225 // * and change their logging levels too. Also, skip sql loggers so
1226 // they
1227 // * do not get effected.
1228 // */
1229 // while(enLogger.hasMoreElements())
1230 // {
1231 // tmpLogger = (Logger)(enLogger.nextElement());
1232 // tmpLogger.setLevel(newLevel);
1233 // }
1234 // Enumeration<Appender> enAppenders = rootLogger.getAllAppenders();
1235 // Appender appender;
1236 // while(enAppenders.hasMoreElements())
1237 // {
1238 // appender = (Appender)enAppenders.nextElement();
1239 //
1240 // if(appender instanceof AsyncAppender)
1241 // {
1242 // AsyncAppender asyncAppender = (AsyncAppender)appender;
1243 // asyncAppender.activateOptions();
1244 //// rfa = (RollingFileAppender)asyncAppender.getAppender("R");
1245 //// rfa.activateOptions();
1246 //// ca = (ConsoleAppender)asyncAppender.getAppender("STDOUT");
1247 //// ca.activateOptions();
1248 // }
1249 // }
1250 //
1251 // }
1252
1253
1254 }