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