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