"rio" work
[jalview.git] / forester / java / src / org / forester / util / ForesterUtil.java
1 // $Id:
2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
4 //
5 // Copyright (C) 2008-2009 Christian M. Zmasek
6 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
7 // All rights reserved
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 //
23 // Contact: phylosoft @ gmail . com
24 // WWW: www.phylosoft.org/forester
25
26 package org.forester.util;
27
28 import java.awt.Color;
29 import java.io.BufferedReader;
30 import java.io.BufferedWriter;
31 import java.io.File;
32 import java.io.FileInputStream;
33 import java.io.FileNotFoundException;
34 import java.io.FileOutputStream;
35 import java.io.FileReader;
36 import java.io.FileWriter;
37 import java.io.IOException;
38 import java.io.InputStream;
39 import java.io.InputStreamReader;
40 import java.io.StringReader;
41 import java.io.Writer;
42 import java.math.BigDecimal;
43 import java.net.URL;
44 import java.text.DateFormat;
45 import java.text.DecimalFormat;
46 import java.text.DecimalFormatSymbols;
47 import java.text.NumberFormat;
48 import java.text.ParseException;
49 import java.text.SimpleDateFormat;
50 import java.util.ArrayList;
51 import java.util.Collection;
52 import java.util.Date;
53 import java.util.Iterator;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Map.Entry;
57 import java.util.Set;
58 import java.util.SortedMap;
59 import java.util.SortedSet;
60 import java.util.TreeMap;
61 import java.util.TreeSet;
62 import java.util.regex.Pattern;
63
64 public final class ForesterUtil {
65
66     public final static String       FILE_SEPARATOR                   = System.getProperty( "file.separator" );
67     public final static String       LINE_SEPARATOR                   = System.getProperty( "line.separator" );
68     public final static String       JAVA_VENDOR                      = System.getProperty( "java.vendor" );
69     public final static String       JAVA_VERSION                     = System.getProperty( "java.version" );
70     public final static String       OS_ARCH                          = System.getProperty( "os.arch" );
71     public final static String       OS_NAME                          = System.getProperty( "os.name" );
72     public final static String       OS_VERSION                       = System.getProperty( "os.version" );
73     public final static Pattern      PARANTHESESABLE_NH_CHARS_PATTERN = Pattern.compile( "[(),;\\s]" );
74     public final static double       ZERO_DIFF                        = 1.0E-9;
75     public static final BigDecimal   NULL_BD                          = new BigDecimal( 0 );
76     public static final NumberFormat FORMATTER_9;
77     public static final NumberFormat FORMATTER_6;
78     public static final NumberFormat FORMATTER_06;
79     public static final NumberFormat FORMATTER_3;
80     static {
81         final DecimalFormatSymbols dfs = new DecimalFormatSymbols();
82         dfs.setDecimalSeparator( '.' );
83         // dfs.setGroupingSeparator( ( char ) 0 );
84         FORMATTER_9 = new DecimalFormat( "#.#########", dfs );
85         FORMATTER_6 = new DecimalFormat( "#.######", dfs );
86         FORMATTER_06 = new DecimalFormat( "0.######", dfs );
87         FORMATTER_3 = new DecimalFormat( "#.###", dfs );
88     }
89
90     private ForesterUtil() {
91     }
92
93     final public static void appendSeparatorIfNotEmpty( final StringBuffer sb, final char separator ) {
94         if ( sb.length() > 0 ) {
95             sb.append( separator );
96         }
97     }
98
99     public static boolean isWindowns() {
100         return ForesterUtil.OS_NAME.toLowerCase().indexOf( "win" ) > -1;
101     }
102
103     final public static String getForesterLibraryInformation() {
104         return "forester " + ForesterConstants.FORESTER_VERSION + " (" + ForesterConstants.FORESTER_DATE + ")";
105     }
106
107     public static boolean seqIsLikelyToBeAa( final String s ) {
108         final String seq = s.toLowerCase();
109         if ( ( seq.indexOf( 'r' ) > -1 ) || ( seq.indexOf( 'd' ) > -1 ) || ( seq.indexOf( 'e' ) > -1 )
110                 || ( seq.indexOf( 'q' ) > -1 ) || ( seq.indexOf( 'h' ) > -1 ) || ( seq.indexOf( 'k' ) > -1 )
111                 || ( seq.indexOf( 'w' ) > -1 ) || ( seq.indexOf( 's' ) > -1 ) || ( seq.indexOf( 'm' ) > -1 )
112                 || ( seq.indexOf( 'p' ) > -1 ) || ( seq.indexOf( 'v' ) > -1 ) ) {
113             return true;
114         }
115         return false;
116     }
117
118     /**
119      * This calculates a color. If value is equal to min the returned color is
120      * minColor, if value is equal to max the returned color is maxColor,
121      * otherwise a color 'proportional' to value is returned.
122      * 
123      * @param value
124      *            the value 
125      * @param min
126      *            the smallest value 
127      * @param max
128      *            the largest value 
129      * @param minColor
130      *            the color for min
131      * @param maxColor
132      *            the color for max
133      * @return a Color
134      */
135     final public static Color calcColor( double value,
136                                          final double min,
137                                          final double max,
138                                          final Color minColor,
139                                          final Color maxColor ) {
140         if ( value < min ) {
141             value = min;
142         }
143         if ( value > max ) {
144             value = max;
145         }
146         final double x = ForesterUtil.calculateColorFactor( value, max, min );
147         final int red = ForesterUtil.calculateColorComponent( minColor.getRed(), maxColor.getRed(), x );
148         final int green = ForesterUtil.calculateColorComponent( minColor.getGreen(), maxColor.getGreen(), x );
149         final int blue = ForesterUtil.calculateColorComponent( minColor.getBlue(), maxColor.getBlue(), x );
150         return new Color( red, green, blue );
151     }
152
153     /**
154      * This calculates a color. If value is equal to min the returned color is
155      * minColor, if value is equal to max the returned color is maxColor, if
156      * value is equal to mean the returned color is meanColor, otherwise a color
157      * 'proportional' to value is returned -- either between min-mean or
158      * mean-max
159      * 
160      * @param value
161      *            the value
162      * @param min
163      *            the smallest value
164      * @param max
165      *            the largest value 
166      * @param mean
167      *            the mean/median value 
168      * @param minColor
169      *            the color for min
170      * @param maxColor
171      *            the color for max
172      * @param meanColor
173      *            the color for mean
174      * @return a Color
175      */
176     final public static Color calcColor( double value,
177                                          final double min,
178                                          final double max,
179                                          final double mean,
180                                          final Color minColor,
181                                          final Color maxColor,
182                                          final Color meanColor ) {
183         if ( value < min ) {
184             value = min;
185         }
186         if ( value > max ) {
187             value = max;
188         }
189         if ( value < mean ) {
190             final double x = ForesterUtil.calculateColorFactor( value, mean, min );
191             final int red = ForesterUtil.calculateColorComponent( minColor.getRed(), meanColor.getRed(), x );
192             final int green = ForesterUtil.calculateColorComponent( minColor.getGreen(), meanColor.getGreen(), x );
193             final int blue = ForesterUtil.calculateColorComponent( minColor.getBlue(), meanColor.getBlue(), x );
194             return new Color( red, green, blue );
195         }
196         else if ( value > mean ) {
197             final double x = ForesterUtil.calculateColorFactor( value, max, mean );
198             final int red = ForesterUtil.calculateColorComponent( meanColor.getRed(), maxColor.getRed(), x );
199             final int green = ForesterUtil.calculateColorComponent( meanColor.getGreen(), maxColor.getGreen(), x );
200             final int blue = ForesterUtil.calculateColorComponent( meanColor.getBlue(), maxColor.getBlue(), x );
201             return new Color( red, green, blue );
202         }
203         else {
204             return meanColor;
205         }
206     }
207
208     /**
209      * Helper method for calcColor methods.
210      * 
211      * @param smallercolor_component_x
212      *            color component the smaller color
213      * @param largercolor_component_x
214      *            color component the larger color
215      * @param x
216      *            factor
217      * @return an int representing a color component
218      */
219     final private static int calculateColorComponent( final double smallercolor_component_x,
220                                                       final double largercolor_component_x,
221                                                       final double x ) {
222         return ( int ) ( smallercolor_component_x + ( ( x * ( largercolor_component_x - smallercolor_component_x ) ) / 255.0 ) );
223     }
224
225     /**
226      * Helper method for calcColor methods.
227      * 
228      * 
229      * @param value
230      *            the value
231      * @param larger
232      *            the largest value
233      * @param smaller
234      *            the smallest value
235      * @return a normalized value between larger and smaller
236      */
237     final private static double calculateColorFactor( final double value, final double larger, final double smaller ) {
238         return ( 255.0 * ( value - smaller ) ) / ( larger - smaller );
239     }
240
241     final public static String collapseWhiteSpace( final String s ) {
242         return s.replaceAll( "[\\s]+", " " );
243     }
244
245     final public static void collection2file( final File file, final Collection<?> data, final String separator )
246             throws IOException {
247         final Writer writer = new BufferedWriter( new FileWriter( file ) );
248         collection2writer( writer, data, separator );
249         writer.close();
250     }
251
252     final public static void collection2writer( final Writer writer, final Collection<?> data, final String separator )
253             throws IOException {
254         boolean first = true;
255         for( final Object object : data ) {
256             if ( !first ) {
257                 writer.write( separator );
258             }
259             else {
260                 first = false;
261             }
262             writer.write( object.toString() );
263         }
264     }
265
266     final public static String colorToHex( final Color color ) {
267         final String rgb = Integer.toHexString( color.getRGB() );
268         return rgb.substring( 2, rgb.length() );
269     }
270
271     synchronized public static void copyFile( final File in, final File out ) throws IOException {
272         final FileInputStream in_s = new FileInputStream( in );
273         final FileOutputStream out_s = new FileOutputStream( out );
274         try {
275             final byte[] buf = new byte[ 1024 ];
276             int i = 0;
277             while ( ( i = in_s.read( buf ) ) != -1 ) {
278                 out_s.write( buf, 0, i );
279             }
280         }
281         catch ( final IOException e ) {
282             throw e;
283         }
284         finally {
285             if ( in_s != null ) {
286                 in_s.close();
287             }
288             if ( out_s != null ) {
289                 out_s.close();
290             }
291         }
292     }
293
294     final public static int countChars( final String str, final char c ) {
295         int count = 0;
296         for( int i = 0; i < str.length(); ++i ) {
297             if ( str.charAt( i ) == c ) {
298                 ++count;
299             }
300         }
301         return count;
302     }
303
304     final public static BufferedWriter createBufferedWriter( final File file ) throws IOException {
305         if ( file.exists() ) {
306             throw new IOException( "[" + file + "] already exists" );
307         }
308         return new BufferedWriter( new FileWriter( file ) );
309     }
310
311     final public static EasyWriter createEasyWriter( final File file ) throws IOException {
312         return new EasyWriter( createBufferedWriter( file ) );
313     }
314
315     final public static BufferedWriter createEasyWriter( final String name ) throws IOException {
316         return createEasyWriter( createFileForWriting( name ) );
317     }
318
319     final public static BufferedWriter createBufferedWriter( final String name ) throws IOException {
320         return new BufferedWriter( new FileWriter( createFileForWriting( name ) ) );
321     }
322
323     final public static File createFileForWriting( final String name ) throws IOException {
324         final File file = new File( name );
325         if ( file.exists() ) {
326             throw new IOException( "[" + name + "] already exists" );
327         }
328         return file;
329     }
330
331     public static void fatalError( final String prg_name, final String message ) {
332         System.err.println();
333         System.err.println( "[" + prg_name + "] > " + message );
334         System.err.println();
335         System.exit( -1 );
336     }
337
338     public static void fatalErrorIfFileNotReadable( final String prg_name, final File file ) {
339         final String error = isReadableFile( file );
340         if ( !isEmpty( error ) ) {
341             System.err.println();
342             System.err.println( "[" + prg_name + "] > " + error );
343             System.err.println();
344             System.exit( -1 );
345         }
346     }
347
348     public static String[] file2array( final File file ) throws IOException {
349         final List<String> list = file2list( file );
350         final String[] ary = new String[ list.size() ];
351         int i = 0;
352         for( final String s : list ) {
353             ary[ i++ ] = s;
354         }
355         return ary;
356     }
357
358     final public static List<String> file2list( final File file ) throws IOException {
359         final List<String> list = new ArrayList<String>();
360         final BufferedReader in = new BufferedReader( new FileReader( file ) );
361         String str;
362         while ( ( str = in.readLine() ) != null ) {
363             str = str.trim();
364             if ( ( str.length() > 0 ) && !str.startsWith( "#" ) ) {
365                 for( final String s : splitString( str ) ) {
366                     list.add( s );
367                 }
368             }
369         }
370         in.close();
371         return list;
372     }
373
374     final public static SortedSet<String> file2set( final File file ) throws IOException {
375         final SortedSet<String> set = new TreeSet<String>();
376         final BufferedReader in = new BufferedReader( new FileReader( file ) );
377         String str;
378         while ( ( str = in.readLine() ) != null ) {
379             str = str.trim();
380             if ( ( str.length() > 0 ) && !str.startsWith( "#" ) ) {
381                 for( final String s : splitString( str ) ) {
382                     set.add( s );
383                 }
384             }
385         }
386         in.close();
387         return set;
388     }
389
390     final public static String getCurrentDateTime() {
391         final DateFormat format = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss" );
392         return format.format( new Date() );
393     }
394
395     final public static String getFileSeparator() {
396         return ForesterUtil.FILE_SEPARATOR;
397     }
398
399     final public static String getFirstLine( final Object source ) throws FileNotFoundException, IOException {
400         BufferedReader reader = null;
401         if ( source instanceof File ) {
402             final File f = ( File ) source;
403             if ( !f.exists() ) {
404                 throw new IOException( "[" + f.getAbsolutePath() + "] does not exist" );
405             }
406             else if ( !f.isFile() ) {
407                 throw new IOException( "[" + f.getAbsolutePath() + "] is not a file" );
408             }
409             else if ( !f.canRead() ) {
410                 throw new IOException( "[" + f.getAbsolutePath() + "] is not a readable" );
411             }
412             reader = new BufferedReader( new FileReader( f ) );
413         }
414         else if ( source instanceof InputStream ) {
415             reader = new BufferedReader( new InputStreamReader( ( InputStream ) source ) );
416         }
417         else if ( source instanceof String ) {
418             reader = new BufferedReader( new StringReader( ( String ) source ) );
419         }
420         else if ( source instanceof StringBuffer ) {
421             reader = new BufferedReader( new StringReader( source.toString() ) );
422         }
423         else if ( source instanceof URL ) {
424             reader = new BufferedReader( new InputStreamReader( ( ( URL ) source ).openStream() ) );
425         }
426         else {
427             throw new IllegalArgumentException( "dont know how to read [" + source.getClass() + "]" );
428         }
429         String line;
430         while ( ( line = reader.readLine() ) != null ) {
431             line = line.trim();
432             if ( !ForesterUtil.isEmpty( line ) ) {
433                 if ( reader != null ) {
434                     reader.close();
435                 }
436                 return line;
437             }
438         }
439         if ( reader != null ) {
440             reader.close();
441         }
442         return line;
443     }
444
445     final public static String getLineSeparator() {
446         return ForesterUtil.LINE_SEPARATOR;
447     }
448
449     final public static void increaseCountingMap( final Map<String, Integer> counting_map, final String item_name ) {
450         if ( !counting_map.containsKey( item_name ) ) {
451             counting_map.put( item_name, 1 );
452         }
453         else {
454             counting_map.put( item_name, counting_map.get( item_name ) + 1 );
455         }
456     }
457
458     final public static boolean isContainsParanthesesableNhCharacter( final String nh ) {
459         return PARANTHESESABLE_NH_CHARS_PATTERN.matcher( nh ).find();
460     }
461
462     final public static boolean isEmpty( final List<?> l ) {
463         if ( ( l == null ) || l.isEmpty() ) {
464             return true;
465         }
466         for( final Object o : l ) {
467             if ( o != null ) {
468                 return false;
469             }
470         }
471         return true;
472     }
473
474     final public static boolean isEmpty( final Set<?> s ) {
475         if ( ( s == null ) || s.isEmpty() ) {
476             return true;
477         }
478         for( final Object o : s ) {
479             if ( o != null ) {
480                 return false;
481             }
482         }
483         return true;
484     }
485
486     final public static boolean isEmpty( final String s ) {
487         return ( ( s == null ) || ( s.length() < 1 ) );
488     }
489
490     final public static boolean isEqual( final double a, final double b ) {
491         return ( ( Math.abs( a - b ) ) < ZERO_DIFF );
492     }
493
494     final public static boolean isEven( final int n ) {
495         return ( n % 2 ) == 0;
496     }
497
498     /**
499      * This determines whether String[] a and String[] b have at least one
500      * String in common (intersect). Returns false if at least one String[] is
501      * null or empty.
502      * 
503      * @param a
504      *            a String[] b a String[]
505      * @return true if both a and b or not empty or null and contain at least
506      *         one element in common false otherwise
507      */
508     final public static boolean isIntersecting( final String[] a, final String[] b ) {
509         if ( ( a == null ) || ( b == null ) ) {
510             return false;
511         }
512         if ( ( a.length < 1 ) || ( b.length < 1 ) ) {
513             return false;
514         }
515         for( final String ai : a ) {
516             for( final String element : b ) {
517                 if ( ( ai != null ) && ( element != null ) && ai.equals( element ) ) {
518                     return true;
519                 }
520             }
521         }
522         return false;
523     }
524
525     final public static double isLargerOrEqualToZero( final double d ) {
526         if ( d > 0.0 ) {
527             return d;
528         }
529         else {
530             return 0.0;
531         }
532     }
533
534     final public static boolean isNull( final BigDecimal s ) {
535         return ( ( s == null ) || ( s.compareTo( NULL_BD ) == 0 ) );
536     }
537
538     final public static String isReadableFile( final File f ) {
539         if ( !f.exists() ) {
540             return "file [" + f + "] does not exist";
541         }
542         if ( f.isDirectory() ) {
543             return "[" + f + "] is a directory";
544         }
545         if ( !f.isFile() ) {
546             return "[" + f + "] is not a file";
547         }
548         if ( !f.canRead() ) {
549             return "file [" + f + "] is not readable";
550         }
551         if ( f.length() < 1 ) {
552             return "file [" + f + "] is empty";
553         }
554         return null;
555     }
556
557     final public static String isReadableFile( final String s ) {
558         return isReadableFile( new File( s ) );
559     }
560
561     final public static String isWritableFile( final File f ) {
562         if ( f.isDirectory() ) {
563             return "[" + f + "] is a directory";
564         }
565         if ( f.exists() ) {
566             return "[" + f + "] already exists";
567         }
568         return null;
569     }
570
571     /**
572      * Helper for method "stringToColor".
573      * <p>
574      * (Last modified: 12/20/03)
575      */
576     final public static int limitRangeForColor( int i ) {
577         if ( i > 255 ) {
578             i = 255;
579         }
580         else if ( i < 0 ) {
581             i = 0;
582         }
583         return i;
584     }
585
586     final public static SortedMap<Object, Integer> listToSortedCountsMap( final List list ) {
587         final SortedMap<Object, Integer> map = new TreeMap<Object, Integer>();
588         for( final Object key : list ) {
589             if ( !map.containsKey( key ) ) {
590                 map.put( key, 1 );
591             }
592             else {
593                 map.put( key, map.get( key ) + 1 );
594             }
595         }
596         return map;
597     }
598
599     final public static void map2file( final File file,
600                                        final Map<?, ?> data,
601                                        final String entry_separator,
602                                        final String data_separator ) throws IOException {
603         final Writer writer = new BufferedWriter( new FileWriter( file ) );
604         map2writer( writer, data, entry_separator, data_separator );
605         writer.close();
606     }
607
608     final public static void map2writer( final Writer writer,
609                                          final Map<?, ?> data,
610                                          final String entry_separator,
611                                          final String data_separator ) throws IOException {
612         boolean first = true;
613         for( final Entry<?, ?> entry : data.entrySet() ) {
614             if ( !first ) {
615                 writer.write( data_separator );
616             }
617             else {
618                 first = false;
619             }
620             writer.write( entry.getKey().toString() );
621             writer.write( entry_separator );
622             writer.write( entry.getValue().toString() );
623         }
624     }
625
626     final public static StringBuffer mapToStringBuffer( final Map map, final String key_value_separator ) {
627         final StringBuffer sb = new StringBuffer();
628         for( final Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
629             final Object key = iter.next();
630             sb.append( key.toString() );
631             sb.append( key_value_separator );
632             sb.append( map.get( key ).toString() );
633             sb.append( ForesterUtil.getLineSeparator() );
634         }
635         return sb;
636     }
637
638     final public static String normalizeString( final String s,
639                                                 final int length,
640                                                 final boolean left_pad,
641                                                 final char pad_char ) {
642         if ( s.length() > length ) {
643             return s.substring( 0, length );
644         }
645         else {
646             final StringBuffer pad = new StringBuffer( length - s.length() );
647             for( int i = 0; i < ( length - s.length() ); ++i ) {
648                 pad.append( pad_char );
649             }
650             if ( left_pad ) {
651                 return pad + s;
652             }
653             else {
654                 return s + pad;
655             }
656         }
657     }
658
659     final public static BufferedReader obtainReader( final Object source ) throws IOException, FileNotFoundException {
660         BufferedReader reader = null;
661         if ( source instanceof File ) {
662             final File f = ( File ) source;
663             if ( !f.exists() ) {
664                 throw new IOException( "\"" + f.getAbsolutePath() + "\" does not exist" );
665             }
666             else if ( !f.isFile() ) {
667                 throw new IOException( "\"" + f.getAbsolutePath() + "\" is not a file" );
668             }
669             else if ( !f.canRead() ) {
670                 throw new IOException( "\"" + f.getAbsolutePath() + "\" is not a readable" );
671             }
672             reader = new BufferedReader( new FileReader( f ) );
673         }
674         else if ( source instanceof InputStream ) {
675             reader = new BufferedReader( new InputStreamReader( ( InputStream ) source ) );
676         }
677         else if ( source instanceof String ) {
678             reader = new BufferedReader( new StringReader( ( String ) source ) );
679         }
680         else if ( source instanceof StringBuffer ) {
681             reader = new BufferedReader( new StringReader( source.toString() ) );
682         }
683         else {
684             throw new IllegalArgumentException( "attempt to parse object of type [" + source.getClass()
685                     + "] (can only parse objects of type File, InputStream, String, or StringBuffer)" );
686         }
687         return reader;
688     }
689
690     final public static StringBuffer pad( final double number, final int size, final char pad, final boolean left_pad ) {
691         return pad( new StringBuffer( number + "" ), size, pad, left_pad );
692     }
693
694     final public static StringBuffer pad( final String string, final int size, final char pad, final boolean left_pad ) {
695         return pad( new StringBuffer( string ), size, pad, left_pad );
696     }
697
698     final public static StringBuffer pad( final StringBuffer string,
699                                           final int size,
700                                           final char pad,
701                                           final boolean left_pad ) {
702         final StringBuffer padding = new StringBuffer();
703         final int s = size - string.length();
704         if ( s < 1 ) {
705             return new StringBuffer( string.substring( 0, size ) );
706         }
707         for( int i = 0; i < s; ++i ) {
708             padding.append( pad );
709         }
710         if ( left_pad ) {
711             return padding.append( string );
712         }
713         else {
714             return string.append( padding );
715         }
716     }
717
718     final public static double parseDouble( final String str ) throws ParseException {
719         if ( ForesterUtil.isEmpty( str ) ) {
720             return 0.0;
721         }
722         return Double.parseDouble( str );
723     }
724
725     final public static int parseInt( final String str ) throws ParseException {
726         if ( ForesterUtil.isEmpty( str ) ) {
727             return 0;
728         }
729         return Integer.parseInt( str );
730     }
731
732     final public static void printArray( final Object[] a ) {
733         for( int i = 0; i < a.length; ++i ) {
734             System.out.println( "[" + i + "]=" + a[ i ] );
735         }
736     }
737
738     final public static void printCountingMap( final Map<String, Integer> counting_map ) {
739         for( final String key : counting_map.keySet() ) {
740             System.out.println( key + ": " + counting_map.get( key ) );
741         }
742     }
743
744     final public static void printErrorMessage( final String prg_name, final String message ) {
745         System.out.println( "[" + prg_name + "] > error: " + message );
746     }
747
748     final public static void printProgramInformation( final String prg_name, final String prg_version, final String date ) {
749         final int l = prg_name.length() + prg_version.length() + date.length() + 4;
750         System.out.println();
751         System.out.println( prg_name + " " + prg_version + " (" + date + ")" );
752         for( int i = 0; i < l; ++i ) {
753             System.out.print( "_" );
754         }
755         System.out.println();
756     }
757
758     final public static void printProgramInformation( final String prg_name,
759                                                       final String desc,
760                                                       final String prg_version,
761                                                       final String date,
762                                                       final String email,
763                                                       final String www,
764                                                       final String based_on ) {
765         String my_prg_name = new String( prg_name );
766         if ( !ForesterUtil.isEmpty( desc ) ) {
767             my_prg_name += ( " - " + desc );
768         }
769         final int l = my_prg_name.length() + prg_version.length() + date.length() + 4;
770         System.out.println();
771         System.out.println( my_prg_name + " " + prg_version + " (" + date + ")" );
772         for( int i = 0; i < l; ++i ) {
773             System.out.print( "_" );
774         }
775         System.out.println();
776         System.out.println();
777         System.out.println( "WWW     : " + www );
778         System.out.println( "Contact : " + email );
779         if ( !ForesterUtil.isEmpty( based_on ) ) {
780             System.out.println( "Based on: " + based_on );
781         }
782         if ( !ForesterUtil.isEmpty( ForesterUtil.JAVA_VERSION ) && !ForesterUtil.isEmpty( ForesterUtil.JAVA_VENDOR ) ) {
783             System.out.println();
784             System.out.println( "[running on Java " + ForesterUtil.JAVA_VERSION + " " + ForesterUtil.JAVA_VENDOR + "]" );
785         }
786         System.out.println();
787     }
788
789     final public static void printProgramInformation( final String prg_name,
790                                                       final String prg_version,
791                                                       final String date,
792                                                       final String email,
793                                                       final String www ) {
794         printProgramInformation( prg_name, null, prg_version, date, email, www, null );
795     }
796
797     final public static void printWarningMessage( final String prg_name, final String message ) {
798         System.out.println( "[" + prg_name + "] > warning: " + message );
799     }
800
801     final public static void programMessage( final String prg_name, final String message ) {
802         System.out.println( "[" + prg_name + "] > " + message );
803     }
804
805     final public static String removeSuffix( final String file_name ) {
806         final int i = file_name.lastIndexOf( '.' );
807         if ( i > 1 ) {
808             return file_name.substring( 0, i );
809         }
810         return file_name;
811     }
812
813     /**
814      * Removes all white space from String s.
815      * 
816      * @return String s with white space removed
817      */
818     final public static String removeWhiteSpace( String s ) {
819         int i;
820         for( i = 0; i <= ( s.length() - 1 ); i++ ) {
821             if ( ( s.charAt( i ) == ' ' ) || ( s.charAt( i ) == '\t' ) || ( s.charAt( i ) == '\n' )
822                     || ( s.charAt( i ) == '\r' ) ) {
823                 s = s.substring( 0, i ) + s.substring( i + 1 );
824                 i--;
825             }
826         }
827         return s;
828     }
829
830     final public static String replaceIllegalNhCharacters( final String nh ) {
831         if ( nh == null ) {
832             return "";
833         }
834         return nh.trim().replaceAll( "[\\[\\]:]+", "_" );
835     }
836
837     final public static String replaceIllegalNhxCharacters( final String nhx ) {
838         if ( nhx == null ) {
839             return "";
840         }
841         return nhx.trim().replaceAll( "[\\[\\](),:;\\s]+", "_" );
842     }
843
844     final public static double round( final double value, final int decimal_place ) {
845         BigDecimal bd = new BigDecimal( value );
846         bd = bd.setScale( decimal_place, BigDecimal.ROUND_HALF_UP );
847         return bd.doubleValue();
848     }
849
850     /**
851      * Rounds d to an int.
852      */
853     final public static int roundToInt( final double d ) {
854         return ( int ) ( d + 0.5 );
855     }
856
857     final public static int roundToInt( final float f ) {
858         return ( int ) ( f + 0.5f );
859     }
860
861     final public static short roundToShort( final double d ) {
862         return ( short ) ( d + 0.5 );
863     }
864
865     final public static String sanitizeString( final String s ) {
866         if ( s == null ) {
867             return "";
868         }
869         else {
870             return s.trim();
871         }
872     }
873
874     final private static String[] splitString( final String str ) {
875         final String regex = "[\\s;,]+";
876         return str.split( regex );
877     }
878
879     final public static String stringArrayToString( final String[] a ) {
880         return stringArrayToString( a, ", " );
881     }
882
883     final public static String stringArrayToString( final String[] a, final String separator ) {
884         final StringBuilder sb = new StringBuilder();
885         if ( ( a != null ) && ( a.length > 0 ) ) {
886             for( int i = 0; i < ( a.length - 1 ); ++i ) {
887                 sb.append( a[ i ] + separator );
888             }
889             sb.append( a[ a.length - 1 ] );
890         }
891         return sb.toString();
892     }
893
894     final public static String[] stringListToArray( final List<String> list ) {
895         if ( list != null ) {
896             final String[] str = new String[ list.size() ];
897             int i = 0;
898             for( final String l : list ) {
899                 str[ i++ ] = l;
900             }
901             return str;
902         }
903         return null;
904     }
905
906     final public static String stringListToString( final List<String> l, final String separator ) {
907         final StringBuilder sb = new StringBuilder();
908         if ( ( l != null ) && ( l.size() > 0 ) ) {
909             for( int i = 0; i < ( l.size() - 1 ); ++i ) {
910                 sb.append( l.get( i ) + separator );
911             }
912             sb.append( l.get( l.size() - 1 ) );
913         }
914         return sb.toString();
915     }
916
917     final public static String[] stringSetToArray( final Set<String> strings ) {
918         final String[] str_array = new String[ strings.size() ];
919         int i = 0;
920         for( final String e : strings ) {
921             str_array[ i++ ] = e;
922         }
923         return str_array;
924     }
925
926     final public static void unexpectedFatalError( final String prg_name, final Exception e ) {
927         System.err.println();
928         System.err.println( "[" + prg_name
929                 + "] > unexpected error (Should not have occured! Please contact program author(s).)" );
930         e.printStackTrace( System.err );
931         System.err.println();
932         System.exit( -1 );
933     }
934
935     final public static void unexpectedFatalError( final String prg_name, final String message ) {
936         System.err.println();
937         System.err.println( "[" + prg_name
938                 + "] > unexpected error. Should not have occured! Please contact program author(s)." );
939         System.err.println( message );
940         System.err.println();
941         System.exit( -1 );
942     }
943
944     final public static void unexpectedFatalError( final String prg_name, final String message, final Exception e ) {
945         System.err.println();
946         System.err.println( "[" + prg_name
947                 + "] > unexpected error. Should not have occured! Please contact program author(s)." );
948         System.err.println( message );
949         e.printStackTrace( System.err );
950         System.err.println();
951         System.exit( -1 );
952     }
953
954     public final static String wordWrap( final String str, final int width ) {
955         final StringBuilder sb = new StringBuilder( str );
956         int start = 0;
957         int ls = -1;
958         int i = 0;
959         while ( i < sb.length() ) {
960             if ( sb.charAt( i ) == ' ' ) {
961                 ls = i;
962             }
963             if ( sb.charAt( i ) == '\n' ) {
964                 ls = -1;
965                 start = i + 1;
966             }
967             if ( i > ( ( start + width ) - 1 ) ) {
968                 if ( ls != -1 ) {
969                     sb.setCharAt( ls, '\n' );
970                     start = ls + 1;
971                     ls = -1;
972                 }
973                 else {
974                     sb.insert( i, '\n' );
975                     start = i + 1;
976                 }
977             }
978             i++;
979         }
980         return sb.toString();
981     }
982 }