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