7b9fefa20e8e724acb9bef843f18f1eed696d0db
[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 String[] file2array( final File file ) throws IOException {
339         final List<String> list = file2list( file );
340         final String[] ary = new String[ list.size() ];
341         int i = 0;
342         for( final String s : list ) {
343             ary[ i++ ] = s;
344         }
345         return ary;
346     }
347
348     final public static List<String> file2list( final File file ) throws IOException {
349         final List<String> list = new ArrayList<String>();
350         final BufferedReader in = new BufferedReader( new FileReader( file ) );
351         String str;
352         while ( ( str = in.readLine() ) != null ) {
353             str = str.trim();
354             if ( ( str.length() > 0 ) && !str.startsWith( "#" ) ) {
355                 for( final String s : splitString( str ) ) {
356                     list.add( s );
357                 }
358             }
359         }
360         in.close();
361         return list;
362     }
363
364     final public static SortedSet<String> file2set( final File file ) throws IOException {
365         final SortedSet<String> set = new TreeSet<String>();
366         final BufferedReader in = new BufferedReader( new FileReader( file ) );
367         String str;
368         while ( ( str = in.readLine() ) != null ) {
369             str = str.trim();
370             if ( ( str.length() > 0 ) && !str.startsWith( "#" ) ) {
371                 for( final String s : splitString( str ) ) {
372                     set.add( s );
373                 }
374             }
375         }
376         in.close();
377         return set;
378     }
379
380     final public static String getCurrentDateTime() {
381         final DateFormat format = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss" );
382         return format.format( new Date() );
383     }
384
385     final public static String getFileSeparator() {
386         return ForesterUtil.FILE_SEPARATOR;
387     }
388
389     final public static String getFirstLine( final Object source ) throws FileNotFoundException, IOException {
390         BufferedReader reader = null;
391         if ( source instanceof File ) {
392             final File f = ( File ) source;
393             if ( !f.exists() ) {
394                 throw new IOException( "[" + f.getAbsolutePath() + "] does not exist" );
395             }
396             else if ( !f.isFile() ) {
397                 throw new IOException( "[" + f.getAbsolutePath() + "] is not a file" );
398             }
399             else if ( !f.canRead() ) {
400                 throw new IOException( "[" + f.getAbsolutePath() + "] is not a readable" );
401             }
402             reader = new BufferedReader( new FileReader( f ) );
403         }
404         else if ( source instanceof InputStream ) {
405             reader = new BufferedReader( new InputStreamReader( ( InputStream ) source ) );
406         }
407         else if ( source instanceof String ) {
408             reader = new BufferedReader( new StringReader( ( String ) source ) );
409         }
410         else if ( source instanceof StringBuffer ) {
411             reader = new BufferedReader( new StringReader( source.toString() ) );
412         }
413         else if ( source instanceof URL ) {
414             reader = new BufferedReader( new InputStreamReader( ( ( URL ) source ).openStream() ) );
415         }
416         else {
417             throw new IllegalArgumentException( "dont know how to read [" + source.getClass() + "]" );
418         }
419         String line;
420         while ( ( line = reader.readLine() ) != null ) {
421             line = line.trim();
422             if ( !ForesterUtil.isEmpty( line ) ) {
423                 if ( reader != null ) {
424                     reader.close();
425                 }
426                 return line;
427             }
428         }
429         if ( reader != null ) {
430             reader.close();
431         }
432         return line;
433     }
434
435     final public static String getLineSeparator() {
436         return ForesterUtil.LINE_SEPARATOR;
437     }
438
439     final public static void increaseCountingMap( final Map<String, Integer> counting_map, final String item_name ) {
440         if ( !counting_map.containsKey( item_name ) ) {
441             counting_map.put( item_name, 1 );
442         }
443         else {
444             counting_map.put( item_name, counting_map.get( item_name ) + 1 );
445         }
446     }
447
448     final public static boolean isContainsParanthesesableNhCharacter( final String nh ) {
449         return PARANTHESESABLE_NH_CHARS_PATTERN.matcher( nh ).find();
450     }
451
452     final public static boolean isEmpty( final List<?> l ) {
453         if ( ( l == null ) || l.isEmpty() ) {
454             return true;
455         }
456         for( final Object o : l ) {
457             if ( o != null ) {
458                 return false;
459             }
460         }
461         return true;
462     }
463
464     final public static boolean isEmpty( final Set<?> s ) {
465         if ( ( s == null ) || s.isEmpty() ) {
466             return true;
467         }
468         for( final Object o : s ) {
469             if ( o != null ) {
470                 return false;
471             }
472         }
473         return true;
474     }
475
476     final public static boolean isEmpty( final String s ) {
477         return ( ( s == null ) || ( s.length() < 1 ) );
478     }
479
480     final public static boolean isEqual( final double a, final double b ) {
481         return ( ( Math.abs( a - b ) ) < ZERO_DIFF );
482     }
483
484     final public static boolean isEven( final int n ) {
485         return n % 2 == 0;
486     }
487
488     /**
489      * This determines whether String[] a and String[] b have at least one
490      * String in common (intersect). Returns false if at least one String[] is
491      * null or empty.
492      * 
493      * @param a
494      *            a String[] b a String[]
495      * @return true if both a and b or not empty or null and contain at least
496      *         one element in common false otherwise
497      */
498     final public static boolean isIntersecting( final String[] a, final String[] b ) {
499         if ( ( a == null ) || ( b == null ) ) {
500             return false;
501         }
502         if ( ( a.length < 1 ) || ( b.length < 1 ) ) {
503             return false;
504         }
505         for( int i = 0; i < a.length; ++i ) {
506             final String ai = a[ i ];
507             for( int j = 0; j < b.length; ++j ) {
508                 if ( ( ai != null ) && ( b[ j ] != null ) && ai.equals( b[ j ] ) ) {
509                     return true;
510                 }
511             }
512         }
513         return false;
514     }
515
516     final public static double isLargerOrEqualToZero( final double d ) {
517         if ( d > 0.0 ) {
518             return d;
519         }
520         else {
521             return 0.0;
522         }
523     }
524
525     final public static boolean isNull( final BigDecimal s ) {
526         return ( ( s == null ) || ( s.compareTo( NULL_BD ) == 0 ) );
527     }
528
529     final public static String isReadableFile( final File f ) {
530         if ( !f.exists() ) {
531             return "file [" + f + "] does not exist";
532         }
533         if ( f.isDirectory() ) {
534             return "[" + f + "] is a directory";
535         }
536         if ( !f.isFile() ) {
537             return "[" + f + "] is not a file";
538         }
539         if ( !f.canRead() ) {
540             return "file [" + f + "] is not readable";
541         }
542         if ( f.length() < 1 ) {
543             return "file [" + f + "] is empty";
544         }
545         return null;
546     }
547
548     final public static String isReadableFile( final String s ) {
549         return isReadableFile( new File( s ) );
550     }
551
552     final public static String isWritableFile( final File f ) {
553         if ( f.isDirectory() ) {
554             return "[" + f + "] is a directory";
555         }
556         if ( f.exists() ) {
557             return "[" + f + "] already exists";
558         }
559         return null;
560     }
561
562     /**
563      * Helper for method "stringToColor".
564      * <p>
565      * (Last modified: 12/20/03)
566      */
567     final public static int limitRangeForColor( int i ) {
568         if ( i > 255 ) {
569             i = 255;
570         }
571         else if ( i < 0 ) {
572             i = 0;
573         }
574         return i;
575     }
576
577     final public static SortedMap<Object, Integer> listToSortedCountsMap( final List list ) {
578         final SortedMap<Object, Integer> map = new TreeMap<Object, Integer>();
579         for( final Object key : list ) {
580             if ( !map.containsKey( key ) ) {
581                 map.put( key, 1 );
582             }
583             else {
584                 map.put( key, map.get( key ) + 1 );
585             }
586         }
587         return map;
588     }
589
590     final public static void map2file( final File file,
591                                        final Map<?, ?> data,
592                                        final String entry_separator,
593                                        final String data_separator ) throws IOException {
594         final Writer writer = new BufferedWriter( new FileWriter( file ) );
595         map2writer( writer, data, entry_separator, data_separator );
596         writer.close();
597     }
598
599     final public static void map2writer( final Writer writer,
600                                          final Map<?, ?> data,
601                                          final String entry_separator,
602                                          final String data_separator ) throws IOException {
603         boolean first = true;
604         for( final Entry<?, ?> entry : data.entrySet() ) {
605             if ( !first ) {
606                 writer.write( data_separator );
607             }
608             else {
609                 first = false;
610             }
611             writer.write( entry.getKey().toString() );
612             writer.write( entry_separator );
613             writer.write( entry.getValue().toString() );
614         }
615     }
616
617     final public static StringBuffer mapToStringBuffer( final Map map, final String key_value_separator ) {
618         final StringBuffer sb = new StringBuffer();
619         for( final Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
620             final Object key = iter.next();
621             sb.append( key.toString() );
622             sb.append( key_value_separator );
623             sb.append( map.get( key ).toString() );
624             sb.append( ForesterUtil.getLineSeparator() );
625         }
626         return sb;
627     }
628
629     final public static String normalizeString( final String s,
630                                                 final int length,
631                                                 final boolean left_pad,
632                                                 final char pad_char ) {
633         if ( s.length() > length ) {
634             return s.substring( 0, length );
635         }
636         else {
637             final StringBuffer pad = new StringBuffer( length - s.length() );
638             for( int i = 0; i < ( length - s.length() ); ++i ) {
639                 pad.append( pad_char );
640             }
641             if ( left_pad ) {
642                 return pad + s;
643             }
644             else {
645                 return s + pad;
646             }
647         }
648     }
649
650     final public static BufferedReader obtainReader( final Object source ) throws IOException, FileNotFoundException {
651         BufferedReader reader = null;
652         if ( source instanceof File ) {
653             final File f = ( File ) source;
654             if ( !f.exists() ) {
655                 throw new IOException( "\"" + f.getAbsolutePath() + "\" does not exist" );
656             }
657             else if ( !f.isFile() ) {
658                 throw new IOException( "\"" + f.getAbsolutePath() + "\" is not a file" );
659             }
660             else if ( !f.canRead() ) {
661                 throw new IOException( "\"" + f.getAbsolutePath() + "\" is not a readable" );
662             }
663             reader = new BufferedReader( new FileReader( f ) );
664         }
665         else if ( source instanceof InputStream ) {
666             reader = new BufferedReader( new InputStreamReader( ( InputStream ) source ) );
667         }
668         else if ( source instanceof String ) {
669             reader = new BufferedReader( new StringReader( ( String ) source ) );
670         }
671         else if ( source instanceof StringBuffer ) {
672             reader = new BufferedReader( new StringReader( source.toString() ) );
673         }
674         else {
675             throw new IllegalArgumentException( "attempt to parse object of type [" + source.getClass()
676                     + "] (can only parse objects of type File, InputStream, String, or StringBuffer)" );
677         }
678         return reader;
679     }
680
681     final public static StringBuffer pad( final double number, final int size, final char pad, final boolean left_pad ) {
682         return pad( new StringBuffer( number + "" ), size, pad, left_pad );
683     }
684
685     final public static StringBuffer pad( final String string, final int size, final char pad, final boolean left_pad ) {
686         return pad( new StringBuffer( string ), size, pad, left_pad );
687     }
688
689     final public static StringBuffer pad( final StringBuffer string,
690                                           final int size,
691                                           final char pad,
692                                           final boolean left_pad ) {
693         final StringBuffer padding = new StringBuffer();
694         final int s = size - string.length();
695         if ( s < 1 ) {
696             return new StringBuffer( string.substring( 0, size ) );
697         }
698         for( int i = 0; i < s; ++i ) {
699             padding.append( pad );
700         }
701         if ( left_pad ) {
702             return padding.append( string );
703         }
704         else {
705             return string.append( padding );
706         }
707     }
708
709     final public static double parseDouble( final String str ) throws ParseException {
710         if ( ForesterUtil.isEmpty( str ) ) {
711             return 0.0;
712         }
713         return Double.parseDouble( str );
714     }
715
716     final public static int parseInt( final String str ) throws ParseException {
717         if ( ForesterUtil.isEmpty( str ) ) {
718             return 0;
719         }
720         return Integer.parseInt( str );
721     }
722
723     final public static void printArray( final Object[] a ) {
724         for( int i = 0; i < a.length; ++i ) {
725             System.out.println( "[" + i + "]=" + a[ i ] );
726         }
727     }
728
729     final public static void printCountingMap( final Map<String, Integer> counting_map ) {
730         for( final String key : counting_map.keySet() ) {
731             System.out.println( key + ": " + counting_map.get( key ) );
732         }
733     }
734
735     final public static void printErrorMessage( final String prg_name, final String message ) {
736         System.out.println( "[" + prg_name + "] > error: " + message );
737     }
738
739     final public static void printProgramInformation( final String prg_name, final String prg_version, final String date ) {
740         final int l = prg_name.length() + prg_version.length() + date.length() + 4;
741         System.out.println();
742         System.out.println( prg_name + " " + prg_version + " (" + date + ")" );
743         for( int i = 0; i < l; ++i ) {
744             System.out.print( "_" );
745         }
746         System.out.println();
747     }
748
749     final public static void printProgramInformation( final String prg_name,
750                                                       final String desc,
751                                                       final String prg_version,
752                                                       final String date,
753                                                       final String email,
754                                                       final String www,
755                                                       final String based_on ) {
756         String my_prg_name = new String( prg_name );
757         if ( !ForesterUtil.isEmpty( desc ) ) {
758             my_prg_name += ( " - " + desc );
759         }
760         final int l = my_prg_name.length() + prg_version.length() + date.length() + 4;
761         System.out.println();
762         System.out.println( my_prg_name + " " + prg_version + " (" + date + ")" );
763         for( int i = 0; i < l; ++i ) {
764             System.out.print( "_" );
765         }
766         System.out.println();
767         System.out.println();
768         System.out.println( "WWW     : " + www );
769         System.out.println( "Contact : " + email );
770         if ( !ForesterUtil.isEmpty( based_on ) ) {
771             System.out.println( "Based on: " + based_on );
772         }
773         if ( !ForesterUtil.isEmpty( ForesterUtil.JAVA_VERSION ) && !ForesterUtil.isEmpty( ForesterUtil.JAVA_VENDOR ) ) {
774             System.out.println();
775             System.out.println( "[running on Java " + ForesterUtil.JAVA_VERSION + " " + ForesterUtil.JAVA_VENDOR + "]" );
776         }
777         System.out.println();
778     }
779
780     final public static void printProgramInformation( final String prg_name,
781                                                       final String prg_version,
782                                                       final String date,
783                                                       final String email,
784                                                       final String www ) {
785         printProgramInformation( prg_name, null, prg_version, date, email, www, null );
786     }
787
788     final public static void printWarningMessage( final String prg_name, final String message ) {
789         System.out.println( "[" + prg_name + "] > warning: " + message );
790     }
791
792     final public static void programMessage( final String prg_name, final String message ) {
793         System.out.println( "[" + prg_name + "] > " + message );
794     }
795
796     final public static String removeSuffix( final String file_name ) {
797         final int i = file_name.lastIndexOf( '.' );
798         if ( i > 1 ) {
799             return file_name.substring( 0, i );
800         }
801         return file_name;
802     }
803
804     /**
805      * Removes all white space from String s.
806      * 
807      * @return String s with white space removed
808      */
809     final public static String removeWhiteSpace( String s ) {
810         int i;
811         for( i = 0; i <= s.length() - 1; i++ ) {
812             if ( ( s.charAt( i ) == ' ' ) || ( s.charAt( i ) == '\t' ) || ( s.charAt( i ) == '\n' )
813                     || ( s.charAt( i ) == '\r' ) ) {
814                 s = s.substring( 0, i ) + s.substring( i + 1 );
815                 i--;
816             }
817         }
818         return s;
819     }
820
821     final public static String replaceIllegalNhCharacters( final String nh ) {
822         if ( nh == null ) {
823             return "";
824         }
825         return nh.trim().replaceAll( "[\\[\\]:]+", "_" );
826     }
827
828     final public static String replaceIllegalNhxCharacters( final String nhx ) {
829         if ( nhx == null ) {
830             return "";
831         }
832         return nhx.trim().replaceAll( "[\\[\\](),:;\\s]+", "_" );
833     }
834
835     final public static double round( final double value, final int decimal_place ) {
836         BigDecimal bd = new BigDecimal( value );
837         bd = bd.setScale( decimal_place, BigDecimal.ROUND_HALF_UP );
838         return bd.doubleValue();
839     }
840
841     /**
842      * Rounds d to an int.
843      */
844     final public static int roundToInt( final double d ) {
845         return ( int ) ( d + 0.5 );
846     }
847
848     final public static int roundToInt( final float f ) {
849         return ( int ) ( f + 0.5f );
850     }
851
852     final public static short roundToShort( final double d ) {
853         return ( short ) ( d + 0.5 );
854     }
855
856     final public static String sanitizeString( final String s ) {
857         if ( s == null ) {
858             return "";
859         }
860         else {
861             return s.trim();
862         }
863     }
864
865     final private static String[] splitString( final String str ) {
866         final String regex = "[\\s;,]+";
867         return str.split( regex );
868     }
869
870     final public static String stringArrayToString( final String[] a ) {
871         return stringArrayToString( a, ", " );
872     }
873
874     final public static String stringArrayToString( final String[] a, final String separator ) {
875         final StringBuilder sb = new StringBuilder();
876         if ( ( a != null ) && ( a.length > 0 ) ) {
877             for( int i = 0; i < a.length - 1; ++i ) {
878                 sb.append( a[ i ] + separator );
879             }
880             sb.append( a[ a.length - 1 ] );
881         }
882         return sb.toString();
883     }
884
885     final public static String[] stringListToArray( final List<String> list ) {
886         if ( list != null ) {
887             final String[] str = new String[ list.size() ];
888             int i = 0;
889             for( final String l : list ) {
890                 str[ i++ ] = l;
891             }
892             return str;
893         }
894         return null;
895     }
896
897     final public static String stringListToString( final List<String> l, final String separator ) {
898         final StringBuilder sb = new StringBuilder();
899         if ( ( l != null ) && ( l.size() > 0 ) ) {
900             for( int i = 0; i < l.size() - 1; ++i ) {
901                 sb.append( l.get( i ) + separator );
902             }
903             sb.append( l.get( l.size() - 1 ) );
904         }
905         return sb.toString();
906     }
907
908     final public static String[] stringSetToArray( final Set<String> strings ) {
909         final String[] str_array = new String[ strings.size() ];
910         int i = 0;
911         for( final String e : strings ) {
912             str_array[ i++ ] = e;
913         }
914         return str_array;
915     }
916
917     final public static void unexpectedFatalError( final String prg_name, final Exception e ) {
918         System.err.println();
919         System.err.println( "[" + prg_name
920                 + "] > unexpected error (Should not have occured! Please contact program author(s).)" );
921         e.printStackTrace( System.err );
922         System.err.println();
923         System.exit( -1 );
924     }
925
926     final public static void unexpectedFatalError( final String prg_name, final String message ) {
927         System.err.println();
928         System.err.println( "[" + prg_name
929                 + "] > unexpected error. Should not have occured! Please contact program author(s)." );
930         System.err.println( message );
931         System.err.println();
932         System.exit( -1 );
933     }
934
935     final public static void unexpectedFatalError( final String prg_name, final String message, final Exception e ) {
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         e.printStackTrace( System.err );
941         System.err.println();
942         System.exit( -1 );
943     }
944
945     public final static String wordWrap( final String str, final int width ) {
946         final StringBuilder sb = new StringBuilder( str );
947         int start = 0;
948         int ls = -1;
949         int i = 0;
950         while ( i < sb.length() ) {
951             if ( sb.charAt( i ) == ' ' ) {
952                 ls = i;
953             }
954             if ( sb.charAt( i ) == '\n' ) {
955                 ls = -1;
956                 start = i + 1;
957             }
958             if ( i > start + width - 1 ) {
959                 if ( ls != -1 ) {
960                     sb.setCharAt( ls, '\n' );
961                     start = ls + 1;
962                     ls = -1;
963                 }
964                 else {
965                     sb.insert( i, '\n' );
966                     start = i + 1;
967                 }
968             }
969             i++;
970         }
971         return sb.toString();
972     }
973 }