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