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