fixing lining up of domains.
[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: https://sites.google.com/site/cmzmasek/home/software/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.net.URLConnection;
45 import java.text.DateFormat;
46 import java.text.DecimalFormat;
47 import java.text.DecimalFormatSymbols;
48 import java.text.NumberFormat;
49 import java.text.ParseException;
50 import java.text.SimpleDateFormat;
51 import java.util.ArrayList;
52 import java.util.Collection;
53 import java.util.Date;
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.Matcher;
63 import java.util.regex.Pattern;
64
65 import org.forester.archaeopteryx.Constants;
66 import org.forester.phylogeny.PhylogenyNode;
67 import org.forester.phylogeny.data.Distribution;
68 import org.forester.phylogeny.data.Sequence;
69 import org.forester.phylogeny.data.Taxonomy;
70 import org.forester.protein.BasicProtein;
71 import org.forester.protein.Domain;
72 import org.forester.protein.Protein;
73 import org.forester.surfacing.SurfacingUtil;
74
75 public final class ForesterUtil {
76
77     public final static String       FILE_SEPARATOR                   = System.getProperty( "file.separator" );
78     public static final NumberFormat FORMATTER_06;
79     public static final NumberFormat FORMATTER_3;
80     public static final NumberFormat FORMATTER_6;
81     public static final NumberFormat FORMATTER_9;
82     public final static String       JAVA_VENDOR                      = System.getProperty( "java.vendor" );
83     public final static String       JAVA_VERSION                     = System.getProperty( "java.version" );
84     public final static String       LINE_SEPARATOR                   = System.getProperty( "line.separator" );
85     public static final String       NCBI_GI                          = "http://www.ncbi.nlm.nih.gov/protein/gi:";
86     public static final String       NCBI_NUCCORE                     = "http://www.ncbi.nlm.nih.gov/nuccore/";
87     public static final String       NCBI_PROTEIN                     = "http://www.ncbi.nlm.nih.gov/protein/";
88     public static final BigDecimal   NULL_BD                          = new BigDecimal( 0 );
89     public final static String       OS_ARCH                          = System.getProperty( "os.arch" );
90     public final static String       OS_NAME                          = System.getProperty( "os.name" );
91     public final static String       OS_VERSION                       = System.getProperty( "os.version" );
92     public static final String       PDB                              = "http://www.pdb.org/pdb/explore/explore.do?pdbId=";
93     public final static String       UNIPROT_KB                       = "http://www.uniprot.org/uniprot/";
94     public final static double       ZERO_DIFF                        = 1.0E-9;
95     private static final Pattern     PARANTHESESABLE_NH_CHARS_PATTERN = Pattern.compile( "[(),;\\s:\\[\\]]" );
96     static {
97         final DecimalFormatSymbols dfs = new DecimalFormatSymbols();
98         dfs.setDecimalSeparator( '.' );
99         // dfs.setGroupingSeparator( ( char ) 0 );
100         FORMATTER_9 = new DecimalFormat( "#.#########", dfs );
101         FORMATTER_6 = new DecimalFormat( "#.######", dfs );
102         FORMATTER_06 = new DecimalFormat( "0.######", dfs );
103         FORMATTER_3 = new DecimalFormat( "#.###", dfs );
104     }
105
106     private ForesterUtil() {
107     }
108
109     final public static void appendSeparatorIfNotEmpty( final StringBuffer sb, final char separator ) {
110         if ( sb.length() > 0 ) {
111             sb.append( separator );
112         }
113     }
114
115     /**
116      * This calculates a color. If value is equal to min the returned color is
117      * minColor, if value is equal to max the returned color is maxColor,
118      * otherwise a color 'proportional' to value is returned.
119      * 
120      * @param value
121      *            the value 
122      * @param min
123      *            the smallest value 
124      * @param max
125      *            the largest value 
126      * @param minColor
127      *            the color for min
128      * @param maxColor
129      *            the color for max
130      * @return a Color
131      */
132     final public static Color calcColor( double value,
133                                          final double min,
134                                          final double max,
135                                          final Color minColor,
136                                          final Color maxColor ) {
137         if ( value < min ) {
138             value = min;
139         }
140         if ( value > max ) {
141             value = max;
142         }
143         final double x = ForesterUtil.calculateColorFactor( value, max, min );
144         final int red = ForesterUtil.calculateColorComponent( minColor.getRed(), maxColor.getRed(), x );
145         final int green = ForesterUtil.calculateColorComponent( minColor.getGreen(), maxColor.getGreen(), x );
146         final int blue = ForesterUtil.calculateColorComponent( minColor.getBlue(), maxColor.getBlue(), x );
147         return new Color( red, green, blue );
148     }
149
150     /**
151      * This calculates a color. If value is equal to min the returned color is
152      * minColor, if value is equal to max the returned color is maxColor, if
153      * value is equal to mean the returned color is meanColor, otherwise a color
154      * 'proportional' to value is returned -- either between min-mean or
155      * mean-max
156      * 
157      * @param value
158      *            the value
159      * @param min
160      *            the smallest value
161      * @param max
162      *            the largest value 
163      * @param mean
164      *            the mean/median value 
165      * @param minColor
166      *            the color for min
167      * @param maxColor
168      *            the color for max
169      * @param meanColor
170      *            the color for mean
171      * @return a Color
172      */
173     final public static Color calcColor( double value,
174                                          final double min,
175                                          final double max,
176                                          final double mean,
177                                          final Color minColor,
178                                          final Color maxColor,
179                                          final Color meanColor ) {
180         if ( value < min ) {
181             value = min;
182         }
183         if ( value > max ) {
184             value = max;
185         }
186         if ( value < mean ) {
187             final double x = ForesterUtil.calculateColorFactor( value, mean, min );
188             final int red = ForesterUtil.calculateColorComponent( minColor.getRed(), meanColor.getRed(), x );
189             final int green = ForesterUtil.calculateColorComponent( minColor.getGreen(), meanColor.getGreen(), x );
190             final int blue = ForesterUtil.calculateColorComponent( minColor.getBlue(), meanColor.getBlue(), x );
191             return new Color( red, green, blue );
192         }
193         else if ( value > mean ) {
194             final double x = ForesterUtil.calculateColorFactor( value, max, mean );
195             final int red = ForesterUtil.calculateColorComponent( meanColor.getRed(), maxColor.getRed(), x );
196             final int green = ForesterUtil.calculateColorComponent( meanColor.getGreen(), maxColor.getGreen(), x );
197             final int blue = ForesterUtil.calculateColorComponent( meanColor.getBlue(), maxColor.getBlue(), x );
198             return new Color( red, green, blue );
199         }
200         else {
201             return meanColor;
202         }
203     }
204
205     public static int calculateOverlap( final Domain domain, final List<Boolean> covered_positions ) {
206         int overlap_count = 0;
207         for( int i = domain.getFrom(); i <= domain.getTo(); ++i ) {
208             if ( ( i < covered_positions.size() ) && ( covered_positions.get( i ) == true ) ) {
209                 ++overlap_count;
210             }
211         }
212         return overlap_count;
213     }
214
215     final public static String collapseWhiteSpace( final String s ) {
216         return s.replaceAll( "[\\s]+", " " );
217     }
218
219     final public static void collection2file( final File file, final Collection<?> data, final String separator )
220             throws IOException {
221         final Writer writer = new BufferedWriter( new FileWriter( file ) );
222         collection2writer( writer, data, separator );
223         writer.close();
224     }
225
226     final public static void collection2writer( final Writer writer, final Collection<?> data, final String separator )
227             throws IOException {
228         boolean first = true;
229         for( final Object object : data ) {
230             if ( !first ) {
231                 writer.write( separator );
232             }
233             else {
234                 first = false;
235             }
236             writer.write( object.toString() );
237         }
238     }
239
240     final public static String colorToHex( final Color color ) {
241         final String rgb = Integer.toHexString( color.getRGB() );
242         return rgb.substring( 2, rgb.length() );
243     }
244
245     synchronized public static void copyFile( final File in, final File out ) throws IOException {
246         final FileInputStream in_s = new FileInputStream( in );
247         final FileOutputStream out_s = new FileOutputStream( out );
248         try {
249             final byte[] buf = new byte[ 1024 ];
250             int i = 0;
251             while ( ( i = in_s.read( buf ) ) != -1 ) {
252                 out_s.write( buf, 0, i );
253             }
254         }
255         catch ( final IOException e ) {
256             throw e;
257         }
258         finally {
259             if ( in_s != null ) {
260                 in_s.close();
261             }
262             if ( out_s != null ) {
263                 out_s.close();
264             }
265         }
266     }
267
268     final public static int countChars( final String str, final char c ) {
269         int count = 0;
270         for( int i = 0; i < str.length(); ++i ) {
271             if ( str.charAt( i ) == c ) {
272                 ++count;
273             }
274         }
275         return count;
276     }
277
278     final public static BufferedWriter createBufferedWriter( final File file ) throws IOException {
279         if ( file.exists() ) {
280             throw new IOException( "[" + file + "] already exists" );
281         }
282         return new BufferedWriter( new FileWriter( file ) );
283     }
284
285     final public static BufferedWriter createBufferedWriter( final String name ) throws IOException {
286         return new BufferedWriter( new FileWriter( createFileForWriting( name ) ) );
287     }
288
289     final public static EasyWriter createEasyWriter( final File file ) throws IOException {
290         return new EasyWriter( createBufferedWriter( file ) );
291     }
292
293     final public static BufferedWriter createEasyWriter( final String name ) throws IOException {
294         return createEasyWriter( createFileForWriting( name ) );
295     }
296
297     final public static File createFileForWriting( final String name ) throws IOException {
298         final File file = new File( name );
299         if ( file.exists() ) {
300             throw new IOException( "[" + name + "] already exists" );
301         }
302         return file;
303     }
304
305     final public static void ensurePresenceOfDate( final PhylogenyNode node ) {
306         if ( !node.getNodeData().isHasDate() ) {
307             node.getNodeData().setDate( new org.forester.phylogeny.data.Date() );
308         }
309     }
310
311     final public static void ensurePresenceOfDistribution( final PhylogenyNode node ) {
312         if ( !node.getNodeData().isHasDistribution() ) {
313             node.getNodeData().setDistribution( new Distribution( "" ) );
314         }
315     }
316
317     public static void ensurePresenceOfSequence( final PhylogenyNode node ) {
318         if ( !node.getNodeData().isHasSequence() ) {
319             node.getNodeData().setSequence( new Sequence() );
320         }
321     }
322
323     public static void ensurePresenceOfTaxonomy( final PhylogenyNode node ) {
324         if ( !node.getNodeData().isHasTaxonomy() ) {
325             node.getNodeData().setTaxonomy( new Taxonomy() );
326         }
327     }
328
329     public static void fatalError( final String message ) {
330         System.err.println();
331         System.err.println( "error: " + message );
332         System.err.println();
333         System.exit( -1 );
334     }
335
336     public static void fatalError( final String prg_name, final String message ) {
337         System.err.println();
338         System.err.println( "[" + prg_name + "] > " + message );
339         System.err.println();
340         System.exit( -1 );
341     }
342
343     public static void fatalErrorIfFileNotReadable( final File file ) {
344         final String error = isReadableFile( file );
345         if ( !isEmpty( error ) ) {
346             System.err.println();
347             System.err.println( "error: " + error );
348             System.err.println();
349             System.exit( -1 );
350         }
351     }
352
353     public static void fatalErrorIfFileNotReadable( final String prg_name, final File file ) {
354         final String error = isReadableFile( file );
355         if ( !isEmpty( error ) ) {
356             System.err.println();
357             System.err.println( "[" + prg_name + "] > " + error );
358             System.err.println();
359             System.exit( -1 );
360         }
361     }
362
363     public static String[][] file22dArray( final File file ) throws IOException {
364         final List<String> list = new ArrayList<String>();
365         final BufferedReader in = new BufferedReader( new FileReader( file ) );
366         String str;
367         while ( ( str = in.readLine() ) != null ) {
368             str = str.trim();
369             if ( ( str.length() > 0 ) && !str.startsWith( "#" ) ) {
370                 list.add( str );
371             }
372         }
373         in.close();
374         final String[][] ary = new String[ list.size() ][ 2 ];
375         final Pattern pa = Pattern.compile( "(\\S+)\\s+(\\S+)" );
376         int i = 0;
377         for( final String s : list ) {
378             final Matcher m = pa.matcher( s );
379             if ( m.matches() ) {
380                 ary[ i ][ 0 ] = m.group( 1 );
381                 ary[ i ][ 1 ] = m.group( 2 );
382                 ++i;
383             }
384             else {
385                 throw new IOException( "unexpcted format: " + s );
386             }
387         }
388         return ary;
389     }
390
391     public static String[] file2array( final File file ) throws IOException {
392         final List<String> list = file2list( file );
393         final String[] ary = new String[ list.size() ];
394         int i = 0;
395         for( final String s : list ) {
396             ary[ i++ ] = s;
397         }
398         return ary;
399     }
400
401     final public static List<String> file2list( final File file ) throws IOException {
402         final List<String> list = new ArrayList<String>();
403         final BufferedReader in = new BufferedReader( new FileReader( file ) );
404         String str;
405         while ( ( str = in.readLine() ) != null ) {
406             str = str.trim();
407             if ( ( str.length() > 0 ) && !str.startsWith( "#" ) ) {
408                 for( final String s : splitString( str ) ) {
409                     list.add( s );
410                 }
411             }
412         }
413         in.close();
414         return list;
415     }
416
417     final public static SortedSet<String> file2set( final File file ) throws IOException {
418         final SortedSet<String> set = new TreeSet<String>();
419         final BufferedReader in = new BufferedReader( new FileReader( file ) );
420         String str;
421         while ( ( str = in.readLine() ) != null ) {
422             str = str.trim();
423             if ( ( str.length() > 0 ) && !str.startsWith( "#" ) ) {
424                 for( final String s : splitString( str ) ) {
425                     set.add( s );
426                 }
427             }
428         }
429         in.close();
430         return set;
431     }
432
433     final public static String getCurrentDateTime() {
434         final DateFormat format = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss" );
435         return format.format( new Date() );
436     }
437
438     final public static String getFileSeparator() {
439         return ForesterUtil.FILE_SEPARATOR;
440     }
441
442     final public static String getFirstLine( final Object source ) throws FileNotFoundException, IOException {
443         BufferedReader reader = null;
444         if ( source instanceof File ) {
445             final File f = ( File ) source;
446             if ( !f.exists() ) {
447                 throw new IOException( "[" + f.getAbsolutePath() + "] does not exist" );
448             }
449             else if ( !f.isFile() ) {
450                 throw new IOException( "[" + f.getAbsolutePath() + "] is not a file" );
451             }
452             else if ( !f.canRead() ) {
453                 throw new IOException( "[" + f.getAbsolutePath() + "] is not a readable" );
454             }
455             reader = new BufferedReader( new FileReader( f ) );
456         }
457         else if ( source instanceof InputStream ) {
458             reader = new BufferedReader( new InputStreamReader( ( InputStream ) source ) );
459         }
460         else if ( source instanceof String ) {
461             reader = new BufferedReader( new StringReader( ( String ) source ) );
462         }
463         else if ( source instanceof StringBuffer ) {
464             reader = new BufferedReader( new StringReader( source.toString() ) );
465         }
466         else if ( source instanceof URL ) {
467             final URLConnection url_connection = ( ( URL ) source ).openConnection();
468             url_connection.setDefaultUseCaches( false );
469             reader = new BufferedReader( new InputStreamReader( url_connection.getInputStream() ) );
470         }
471         else {
472             throw new IllegalArgumentException( "dont know how to read [" + source.getClass() + "]" );
473         }
474         String line;
475         while ( ( line = reader.readLine() ) != null ) {
476             line = line.trim();
477             if ( !ForesterUtil.isEmpty( line ) ) {
478                 if ( reader != null ) {
479                     reader.close();
480                 }
481                 return line;
482             }
483         }
484         if ( reader != null ) {
485             reader.close();
486         }
487         return line;
488     }
489
490     final public static String getForesterLibraryInformation() {
491         return "forester " + ForesterConstants.FORESTER_VERSION + " (" + ForesterConstants.FORESTER_DATE + ")";
492     }
493
494     final public static String getLineSeparator() {
495         return ForesterUtil.LINE_SEPARATOR;
496     }
497
498     final public static void increaseCountingMap( final Map<String, Integer> counting_map, final String item_name ) {
499         if ( !counting_map.containsKey( item_name ) ) {
500             counting_map.put( item_name, 1 );
501         }
502         else {
503             counting_map.put( item_name, counting_map.get( item_name ) + 1 );
504         }
505     }
506
507     final public static boolean isEmpty( final List<?> l ) {
508         if ( ( l == null ) || l.isEmpty() ) {
509             return true;
510         }
511         for( final Object o : l ) {
512             if ( o != null ) {
513                 return false;
514             }
515         }
516         return true;
517     }
518
519     final public static boolean isEmpty( final Set<?> s ) {
520         if ( ( s == null ) || s.isEmpty() ) {
521             return true;
522         }
523         for( final Object o : s ) {
524             if ( o != null ) {
525                 return false;
526             }
527         }
528         return true;
529     }
530
531     final public static boolean isEmpty( final String s ) {
532         return ( ( s == null ) || ( s.length() < 1 ) );
533     }
534
535     /**
536      * Returns true is Domain domain falls in an uninterrupted stretch of
537      * covered positions.
538      * 
539      * @param domain
540      * @param covered_positions
541      * @return
542      */
543     public static boolean isEngulfed( final Domain domain, final List<Boolean> covered_positions ) {
544         for( int i = domain.getFrom(); i <= domain.getTo(); ++i ) {
545             if ( ( i >= covered_positions.size() ) || ( covered_positions.get( i ) != true ) ) {
546                 return false;
547             }
548         }
549         return true;
550     }
551
552     final public static boolean isEqual( final double a, final double b ) {
553         return ( ( Math.abs( a - b ) ) < ZERO_DIFF );
554     }
555
556     final public static boolean isEven( final int n ) {
557         return ( n % 2 ) == 0;
558     }
559
560     /**
561      * This determines whether String[] a and String[] b have at least one
562      * String in common (intersect). Returns false if at least one String[] is
563      * null or empty.
564      * 
565      * @param a
566      *            a String[] b a String[]
567      * @return true if both a and b or not empty or null and contain at least
568      *         one element in common false otherwise
569      */
570     final public static boolean isIntersecting( final String[] a, final String[] b ) {
571         if ( ( a == null ) || ( b == null ) ) {
572             return false;
573         }
574         if ( ( a.length < 1 ) || ( b.length < 1 ) ) {
575             return false;
576         }
577         for( final String ai : a ) {
578             for( final String element : b ) {
579                 if ( ( ai != null ) && ( element != null ) && ai.equals( element ) ) {
580                     return true;
581                 }
582             }
583         }
584         return false;
585     }
586
587     final public static double isLargerOrEqualToZero( final double d ) {
588         if ( d > 0.0 ) {
589             return d;
590         }
591         else {
592             return 0.0;
593         }
594     }
595
596     public final static boolean isMac() {
597         try {
598             return OS_NAME.toLowerCase().startsWith( "mac" );
599         }
600         catch ( final Exception e ) {
601             ForesterUtil.printWarningMessage( Constants.PRG_NAME, "minor error: " + e );
602             return false;
603         }
604     }
605
606     final public static boolean isNull( final BigDecimal s ) {
607         return ( ( s == null ) || ( s.compareTo( NULL_BD ) == 0 ) );
608     }
609
610     final public static String isReadableFile( final File f ) {
611         if ( !f.exists() ) {
612             return "file [" + f + "] does not exist";
613         }
614         if ( f.isDirectory() ) {
615             return "[" + f + "] is a directory";
616         }
617         if ( !f.isFile() ) {
618             return "[" + f + "] is not a file";
619         }
620         if ( !f.canRead() ) {
621             return "file [" + f + "] is not readable";
622         }
623         if ( f.length() < 1 ) {
624             return "file [" + f + "] is empty";
625         }
626         return null;
627     }
628
629     final public static String isReadableFile( final String s ) {
630         return isReadableFile( new File( s ) );
631     }
632
633     public final static boolean isWindows() {
634         try {
635             return OS_NAME.toLowerCase().indexOf( "win" ) > -1;
636         }
637         catch ( final Exception e ) {
638             ForesterUtil.printWarningMessage( Constants.PRG_NAME, "minor error: " + e );
639             return false;
640         }
641     }
642
643     final public static String isWritableFile( final File f ) {
644         if ( f.isDirectory() ) {
645             return "[" + f + "] is a directory";
646         }
647         if ( f.exists() ) {
648             return "[" + f + "] already exists";
649         }
650         return null;
651     }
652
653     /**
654      * Helper for method "stringToColor".
655      * <p>
656      * (Last modified: 12/20/03)
657      */
658     final public static int limitRangeForColor( int i ) {
659         if ( i > 255 ) {
660             i = 255;
661         }
662         else if ( i < 0 ) {
663             i = 0;
664         }
665         return i;
666     }
667
668     final public static SortedMap<Object, Integer> listToSortedCountsMap( final List<?> list ) {
669         final SortedMap<Object, Integer> map = new TreeMap<Object, Integer>();
670         for( final Object key : list ) {
671             if ( !map.containsKey( key ) ) {
672                 map.put( key, 1 );
673             }
674             else {
675                 map.put( key, map.get( key ) + 1 );
676             }
677         }
678         return map;
679     }
680
681     final public static void map2file( final File file,
682                                        final Map<?, ?> data,
683                                        final String entry_separator,
684                                        final String data_separator ) throws IOException {
685         final Writer writer = new BufferedWriter( new FileWriter( file ) );
686         map2writer( writer, data, entry_separator, data_separator );
687         writer.close();
688     }
689
690     final public static void map2writer( final Writer writer,
691                                          final Map<?, ?> data,
692                                          final String entry_separator,
693                                          final String data_separator ) throws IOException {
694         boolean first = true;
695         for( final Entry<?, ?> entry : data.entrySet() ) {
696             if ( !first ) {
697                 writer.write( data_separator );
698             }
699             else {
700                 first = false;
701             }
702             writer.write( entry.getKey().toString() );
703             writer.write( entry_separator );
704             writer.write( entry.getValue().toString() );
705         }
706     }
707
708     final public static StringBuffer mapToStringBuffer( final Map<Object, Object> map, final String key_value_separator ) {
709         final StringBuffer sb = new StringBuffer();
710         for( final Object key : map.keySet() ) {
711             sb.append( key.toString() );
712             sb.append( key_value_separator );
713             sb.append( map.get( key ).toString() );
714             sb.append( ForesterUtil.getLineSeparator() );
715         }
716         return sb;
717     }
718
719     final public static String normalizeString( final String s,
720                                                 final int length,
721                                                 final boolean left_pad,
722                                                 final char pad_char ) {
723         if ( s.length() > length ) {
724             return s.substring( 0, length );
725         }
726         else {
727             final StringBuffer pad = new StringBuffer( length - s.length() );
728             for( int i = 0; i < ( length - s.length() ); ++i ) {
729                 pad.append( pad_char );
730             }
731             if ( left_pad ) {
732                 return pad + s;
733             }
734             else {
735                 return s + pad;
736             }
737         }
738     }
739
740     public final static Color obtainColorDependingOnTaxonomyGroup( final String tax_group ) {
741         if ( !ForesterUtil.isEmpty( tax_group ) ) {
742             if ( tax_group.equals( TaxonomyGroups.DEUTEROSTOMIA ) ) {
743                 return TaxonomyColors.DEUTEROSTOMIA_COLOR;
744             }
745             else if ( tax_group.equals( TaxonomyGroups.PROTOSTOMIA ) ) {
746                 return TaxonomyColors.PROTOSTOMIA_COLOR;
747             }
748             else if ( tax_group.equals( TaxonomyGroups.CNIDARIA ) ) {
749                 return TaxonomyColors.CNIDARIA_COLOR;
750             }
751             else if ( tax_group.equals( TaxonomyGroups.PLACOZOA ) ) {
752                 return TaxonomyColors.PLACOZOA_COLOR;
753             }
754             else if ( tax_group.equals( TaxonomyGroups.CTENOPHORA ) ) {
755                 return TaxonomyColors.CTENOPHORA_COLOR;
756             }
757             else if ( tax_group.equals( TaxonomyGroups.PORIFERA ) ) {
758                 return TaxonomyColors.PORIFERA_COLOR;
759             }
760             else if ( tax_group.equals( TaxonomyGroups.CHOANOFLAGELLIDA ) ) {
761                 return TaxonomyColors.CHOANOFLAGELLIDA;
762             }
763             else if ( tax_group.equals( TaxonomyGroups.ICHTHYOPHONIDA_FILASTEREA ) ) {
764                 return TaxonomyColors.ICHTHYOSPOREA_AND_FILASTEREA;
765             }
766             else if ( tax_group.equals( TaxonomyGroups.DIKARYA ) ) {
767                 return TaxonomyColors.DIKARYA_COLOR;
768             }
769             else if ( tax_group.equalsIgnoreCase( TaxonomyGroups.FUNGI )
770                     || tax_group.equalsIgnoreCase( TaxonomyGroups.OTHER_FUNGI ) ) {
771                 return TaxonomyColors.OTHER_FUNGI_COLOR;
772             }
773             else if ( tax_group.equals( TaxonomyGroups.NUCLEARIIDAE_AND_FONTICULA_GROUP ) ) {
774                 return TaxonomyColors.NUCLEARIIDAE_AND_FONTICULA_GROUP_COLOR;
775             }
776             else if ( tax_group.equals( TaxonomyGroups.AMOEBOZOA ) ) {
777                 return TaxonomyColors.AMOEBOZOA_COLOR;
778             }
779             else if ( tax_group.equals( TaxonomyGroups.EMBRYOPHYTA ) ) {
780                 return TaxonomyColors.EMBRYOPHYTA_COLOR;
781             }
782             else if ( tax_group.equals( TaxonomyGroups.CHLOROPHYTA ) ) {
783                 return TaxonomyColors.CHLOROPHYTA_COLOR;
784             }
785             else if ( tax_group.equals( TaxonomyGroups.RHODOPHYTA ) ) {
786                 return TaxonomyColors.RHODOPHYTA_COLOR;
787             }
788             else if ( tax_group.equals( TaxonomyGroups.HACROBIA ) ) {
789                 return TaxonomyColors.HACROBIA_COLOR;
790             }
791             else if ( tax_group.equals( TaxonomyGroups.GLAUCOCYSTOPHYCEAE ) ) {
792                 return TaxonomyColors.GLAUCOPHYTA_COLOR;
793             }
794             else if ( tax_group.equals( TaxonomyGroups.STRAMENOPILES ) ) {
795                 return TaxonomyColors.STRAMENOPILES_COLOR;
796             }
797             else if ( tax_group.equals( TaxonomyGroups.ALVEOLATA ) ) {
798                 return TaxonomyColors.ALVEOLATA_COLOR;
799             }
800             else if ( tax_group.equals( TaxonomyGroups.RHIZARIA ) ) {
801                 return TaxonomyColors.RHIZARIA_COLOR;
802             }
803             else if ( tax_group.equals( TaxonomyGroups.EXCAVATA ) ) {
804                 return TaxonomyColors.EXCAVATA_COLOR;
805             }
806             else if ( tax_group.equals( TaxonomyGroups.APUSOZOA ) ) {
807                 return TaxonomyColors.APUSOZOA_COLOR;
808             }
809             else if ( tax_group.equals( TaxonomyGroups.ARCHAEA ) ) {
810                 return TaxonomyColors.ARCHAEA_COLOR;
811             }
812             else if ( tax_group.equals( TaxonomyGroups.BACTERIA ) ) {
813                 return TaxonomyColors.BACTERIA_COLOR;
814             }
815         }
816         return null;
817     }
818
819     public final static String obtainNormalizedTaxonomyGroup( final String tax ) {
820         if ( tax.equalsIgnoreCase( TaxonomyGroups.DEUTEROSTOMIA ) ) {
821             return TaxonomyGroups.DEUTEROSTOMIA;
822         }
823         else if ( tax.equalsIgnoreCase( TaxonomyGroups.PROTOSTOMIA ) ) {
824             return TaxonomyGroups.PROTOSTOMIA;
825         }
826         else if ( tax.equalsIgnoreCase( TaxonomyGroups.CNIDARIA ) ) {
827             return TaxonomyGroups.CNIDARIA;
828         }
829         else if ( tax.toLowerCase().startsWith( "trichoplax" ) || tax.equalsIgnoreCase( TaxonomyGroups.PLACOZOA ) ) {
830             return TaxonomyGroups.PLACOZOA;
831         }
832         else if ( tax.toLowerCase().startsWith( "mnemiopsis" ) || tax.equalsIgnoreCase( TaxonomyGroups.CTENOPHORA ) ) {
833             return TaxonomyGroups.CTENOPHORA;
834         }
835         else if ( tax.toLowerCase().startsWith( "amphimedon" ) || tax.equalsIgnoreCase( TaxonomyGroups.PORIFERA ) ) {
836             return TaxonomyGroups.PORIFERA;
837         }
838         else if ( tax.equalsIgnoreCase( "codonosigidae" ) || tax.equalsIgnoreCase( TaxonomyGroups.CHOANOFLAGELLIDA ) ) {
839             return TaxonomyGroups.CHOANOFLAGELLIDA;
840         }
841         else if ( tax.toLowerCase().startsWith( TaxonomyGroups.ICHTHYOPHONIDA_FILASTEREA )
842                 || tax.toLowerCase().startsWith( "ichthyophonida and filasterea" )
843                 || tax.toLowerCase().startsWith( "ichthyosporea & filasterea" )
844                 || tax.toLowerCase().startsWith( "ichthyosporea and filasterea" ) ) {
845             return TaxonomyGroups.ICHTHYOPHONIDA_FILASTEREA;
846         }
847         else if ( tax.equalsIgnoreCase( TaxonomyGroups.DIKARYA ) ) {
848             return TaxonomyGroups.DIKARYA;
849         }
850         else if ( tax.equalsIgnoreCase( TaxonomyGroups.FUNGI ) || tax.equalsIgnoreCase( TaxonomyGroups.OTHER_FUNGI ) ) {
851             return TaxonomyGroups.OTHER_FUNGI;
852         }
853         else if ( tax.toLowerCase().startsWith( "nucleariidae and fonticula" ) ) {
854             return TaxonomyGroups.NUCLEARIIDAE_AND_FONTICULA_GROUP;
855         }
856         else if ( tax.equalsIgnoreCase( TaxonomyGroups.AMOEBOZOA ) ) {
857             return TaxonomyGroups.AMOEBOZOA;
858         }
859         else if ( tax.equalsIgnoreCase( TaxonomyGroups.EMBRYOPHYTA ) ) {
860             return TaxonomyGroups.EMBRYOPHYTA;
861         }
862         else if ( tax.equalsIgnoreCase( TaxonomyGroups.CHLOROPHYTA ) ) {
863             return TaxonomyGroups.CHLOROPHYTA;
864         }
865         else if ( tax.equalsIgnoreCase( TaxonomyGroups.RHODOPHYTA ) ) {
866             return TaxonomyGroups.RHODOPHYTA;
867         }
868         else if ( tax.toLowerCase().startsWith( TaxonomyGroups.HACROBIA ) ) {
869             return TaxonomyGroups.HACROBIA;
870         }
871         else if ( tax.equalsIgnoreCase( TaxonomyGroups.GLAUCOCYSTOPHYCEAE ) || tax.equalsIgnoreCase( "glaucophyta" ) ) {
872             return TaxonomyGroups.GLAUCOCYSTOPHYCEAE;
873         }
874         else if ( tax.equalsIgnoreCase( TaxonomyGroups.STRAMENOPILES ) ) {
875             return TaxonomyGroups.STRAMENOPILES;
876         }
877         else if ( tax.equalsIgnoreCase( TaxonomyGroups.ALVEOLATA ) ) {
878             return TaxonomyGroups.ALVEOLATA;
879         }
880         else if ( tax.equalsIgnoreCase( TaxonomyGroups.RHIZARIA ) ) {
881             return TaxonomyGroups.RHIZARIA;
882         }
883         else if ( tax.equalsIgnoreCase( TaxonomyGroups.EXCAVATA ) ) {
884             return TaxonomyGroups.EXCAVATA;
885         }
886         else if ( tax.equalsIgnoreCase( TaxonomyGroups.APUSOZOA ) ) {
887             return TaxonomyGroups.APUSOZOA;
888         }
889         else if ( tax.equalsIgnoreCase( TaxonomyGroups.ARCHAEA ) ) {
890             return TaxonomyGroups.ARCHAEA;
891         }
892         else if ( tax.equalsIgnoreCase( TaxonomyGroups.BACTERIA ) ) {
893             return TaxonomyGroups.BACTERIA;
894         }
895         return null;
896     }
897
898     final public static BufferedReader obtainReader( final Object source ) throws IOException, FileNotFoundException {
899         BufferedReader reader = null;
900         if ( source instanceof File ) {
901             final File f = ( File ) source;
902             if ( !f.exists() ) {
903                 throw new IOException( "\"" + f.getAbsolutePath() + "\" does not exist" );
904             }
905             else if ( !f.isFile() ) {
906                 throw new IOException( "\"" + f.getAbsolutePath() + "\" is not a file" );
907             }
908             else if ( !f.canRead() ) {
909                 throw new IOException( "\"" + f.getAbsolutePath() + "\" is not a readable" );
910             }
911             reader = new BufferedReader( new FileReader( f ) );
912         }
913         else if ( source instanceof InputStream ) {
914             reader = new BufferedReader( new InputStreamReader( ( InputStream ) source ) );
915         }
916         else if ( source instanceof String ) {
917             reader = new BufferedReader( new StringReader( ( String ) source ) );
918         }
919         else if ( source instanceof StringBuffer ) {
920             reader = new BufferedReader( new StringReader( source.toString() ) );
921         }
922         else {
923             throw new IllegalArgumentException( "attempt to parse object of type [" + source.getClass()
924                     + "] (can only parse objects of type File, InputStream, String, or StringBuffer)" );
925         }
926         return reader;
927     }
928
929     public final static void outOfMemoryError( final OutOfMemoryError e ) {
930         System.err.println();
931         System.err.println( "Java memory allocation might be too small, try \"-Xmx2048m\" java command line option" );
932         System.err.println();
933         e.printStackTrace( System.err );
934         System.err.println();
935         System.exit( -1 );
936     }
937
938     final public static StringBuffer pad( final double number, final int size, final char pad, final boolean left_pad ) {
939         return pad( new StringBuffer( number + "" ), size, pad, left_pad );
940     }
941
942     final public static StringBuffer pad( final String string, final int size, final char pad, final boolean left_pad ) {
943         return pad( new StringBuffer( string ), size, pad, left_pad );
944     }
945
946     final public static StringBuffer pad( final StringBuffer string,
947                                           final int size,
948                                           final char pad,
949                                           final boolean left_pad ) {
950         final StringBuffer padding = new StringBuffer();
951         final int s = size - string.length();
952         if ( s < 1 ) {
953             return new StringBuffer( string.substring( 0, size ) );
954         }
955         for( int i = 0; i < s; ++i ) {
956             padding.append( pad );
957         }
958         if ( left_pad ) {
959             return padding.append( string );
960         }
961         else {
962             return string.append( padding );
963         }
964     }
965
966     final public static double parseDouble( final String str ) throws ParseException {
967         if ( ForesterUtil.isEmpty( str ) ) {
968             return 0.0;
969         }
970         return Double.parseDouble( str );
971     }
972
973     final public static int parseInt( final String str ) throws ParseException {
974         if ( ForesterUtil.isEmpty( str ) ) {
975             return 0;
976         }
977         return Integer.parseInt( str );
978     }
979
980     final public static void printArray( final Object[] a ) {
981         for( int i = 0; i < a.length; ++i ) {
982             System.out.println( "[" + i + "]=" + a[ i ] );
983         }
984     }
985
986     final public static void printCountingMap( final Map<String, Integer> counting_map ) {
987         for( final String key : counting_map.keySet() ) {
988             System.out.println( key + ": " + counting_map.get( key ) );
989         }
990     }
991
992     final public static void printErrorMessage( final String prg_name, final String message ) {
993         System.err.println( "[" + prg_name + "] > error: " + message );
994     }
995
996     final public static void printProgramInformation( final String prg_name, final String prg_version, final String date ) {
997         final int l = prg_name.length() + prg_version.length() + date.length() + 4;
998         System.out.println();
999         System.out.println( prg_name + " " + prg_version + " (" + date + ")" );
1000         for( int i = 0; i < l; ++i ) {
1001             System.out.print( "_" );
1002         }
1003         System.out.println();
1004     }
1005
1006     final public static void printProgramInformation( final String prg_name,
1007                                                       final String prg_version,
1008                                                       final String date,
1009                                                       final String email,
1010                                                       final String www ) {
1011         printProgramInformation( prg_name, null, prg_version, date, email, www, null );
1012     }
1013
1014     final public static void printProgramInformation( final String prg_name,
1015                                                       final String desc,
1016                                                       final String prg_version,
1017                                                       final String date,
1018                                                       final String email,
1019                                                       final String www,
1020                                                       final String based_on ) {
1021         String my_prg_name = new String( prg_name );
1022         if ( !ForesterUtil.isEmpty( desc ) ) {
1023             my_prg_name += ( " - " + desc );
1024         }
1025         final int l = my_prg_name.length() + prg_version.length() + date.length() + 4;
1026         System.out.println();
1027         System.out.println( my_prg_name + " " + prg_version + " (" + date + ")" );
1028         for( int i = 0; i < l; ++i ) {
1029             System.out.print( "_" );
1030         }
1031         System.out.println();
1032         System.out.println();
1033         System.out.println( "WWW     : " + www );
1034         System.out.println( "Contact : " + email );
1035         if ( !ForesterUtil.isEmpty( based_on ) ) {
1036             System.out.println( "Based on: " + based_on );
1037         }
1038         if ( !ForesterUtil.isEmpty( ForesterUtil.JAVA_VERSION ) && !ForesterUtil.isEmpty( ForesterUtil.JAVA_VENDOR ) ) {
1039             System.out.println();
1040             System.out.println( "[running on Java " + ForesterUtil.JAVA_VERSION + " " + ForesterUtil.JAVA_VENDOR + "]" );
1041         }
1042         System.out.println();
1043     }
1044
1045     final public static void printWarningMessage( final String prg_name, final String message ) {
1046         System.out.println( "[" + prg_name + "] > warning: " + message );
1047     }
1048
1049     final public static void programMessage( final String prg_name, final String message ) {
1050         System.out.println( "[" + prg_name + "] > " + message );
1051     }
1052
1053     /**
1054      * 
1055      * Example regarding engulfment: ------------0.1 ----------0.2 --0.3 =>
1056      * domain with 0.3 is ignored
1057      * 
1058      * -----------0.1 ----------0.2 --0.3 => domain with 0.3 is ignored
1059      * 
1060      * 
1061      * ------------0.1 ----------0.3 --0.2 => domains with 0.3 and 0.2 are _not_
1062      * ignored
1063      * 
1064      * @param max_allowed_overlap
1065      *            maximal allowed overlap (inclusive) to be still considered not
1066      *            overlapping (zero or negative value to allow any overlap)
1067      * @param remove_engulfed_domains
1068      *            to remove domains which are completely engulfed by coverage of
1069      *            domains with better support
1070      * @param protein
1071      * @return
1072      */
1073     public static Protein removeOverlappingDomains( final int max_allowed_overlap,
1074                                                     final boolean remove_engulfed_domains,
1075                                                     final Protein protein ) {
1076         final Protein pruned_protein = new BasicProtein( protein.getProteinId().getId(), protein.getSpecies()
1077                 .getSpeciesId(), protein.getLength() );
1078         final List<Domain> sorted = SurfacingUtil.sortDomainsWithAscendingConfidenceValues( protein );
1079         final List<Boolean> covered_positions = new ArrayList<Boolean>();
1080         for( final Domain domain : sorted ) {
1081             if ( ( ( max_allowed_overlap < 0 ) || ( ForesterUtil.calculateOverlap( domain, covered_positions ) <= max_allowed_overlap ) )
1082                     && ( !remove_engulfed_domains || !isEngulfed( domain, covered_positions ) ) ) {
1083                 final int covered_positions_size = covered_positions.size();
1084                 for( int i = covered_positions_size; i < domain.getFrom(); ++i ) {
1085                     covered_positions.add( false );
1086                 }
1087                 final int new_covered_positions_size = covered_positions.size();
1088                 for( int i = domain.getFrom(); i <= domain.getTo(); ++i ) {
1089                     if ( i < new_covered_positions_size ) {
1090                         covered_positions.set( i, true );
1091                     }
1092                     else {
1093                         covered_positions.add( true );
1094                     }
1095                 }
1096                 pruned_protein.addProteinDomain( domain );
1097             }
1098         }
1099         return pruned_protein;
1100     }
1101
1102     final public static String removeSuffix( final String file_name ) {
1103         final int i = file_name.lastIndexOf( '.' );
1104         if ( i > 1 ) {
1105             return file_name.substring( 0, i );
1106         }
1107         return file_name;
1108     }
1109
1110     /**
1111      * Removes all white space from String s.
1112      * 
1113      * @return String s with white space removed
1114      */
1115     final public static String removeWhiteSpace( String s ) {
1116         int i;
1117         for( i = 0; i <= ( s.length() - 1 ); i++ ) {
1118             if ( ( s.charAt( i ) == ' ' ) || ( s.charAt( i ) == '\t' ) || ( s.charAt( i ) == '\n' )
1119                     || ( s.charAt( i ) == '\r' ) ) {
1120                 s = s.substring( 0, i ) + s.substring( i + 1 );
1121                 i--;
1122             }
1123         }
1124         return s;
1125     }
1126
1127     final public static String replaceIllegalNhxCharacters( final String nhx ) {
1128         if ( nhx == null ) {
1129             return "";
1130         }
1131         return nhx.trim().replaceAll( "[\\[\\]']+", "_" );
1132     }
1133
1134     final public static double round( final double value, final int decimal_place ) {
1135         BigDecimal bd = new BigDecimal( value );
1136         bd = bd.setScale( decimal_place, BigDecimal.ROUND_HALF_UP );
1137         return bd.doubleValue();
1138     }
1139
1140     /**
1141      * Rounds d to an int.
1142      */
1143     final public static int roundToInt( final double d ) {
1144         return ( int ) ( d + 0.5 );
1145     }
1146
1147     final public static int roundToInt( final float f ) {
1148         return ( int ) ( f + 0.5f );
1149     }
1150
1151     final public static short roundToShort( final double d ) {
1152         return ( short ) ( d + 0.5 );
1153     }
1154
1155     final public static String sanitizeString( final String s ) {
1156         if ( s == null ) {
1157             return "";
1158         }
1159         else {
1160             return s.trim();
1161         }
1162     }
1163
1164     public final static StringBuilder santitizeStringForNH( String data ) {
1165         data = data.replaceAll( "\\s+", " " ).trim();
1166         final StringBuilder sb = new StringBuilder();
1167         if ( data.length() > 0 ) {
1168             final boolean single_pars = data.indexOf( '\'' ) > -1;
1169             final boolean double_pars = data.indexOf( '"' ) > -1;
1170             if ( single_pars && double_pars ) {
1171                 data = data.replace( '\'', '`' );
1172                 sb.append( '\'' );
1173                 sb.append( data );
1174                 sb.append( '\'' );
1175             }
1176             else if ( single_pars ) {
1177                 sb.append( '"' );
1178                 sb.append( data );
1179                 sb.append( '"' );
1180             }
1181             else if ( PARANTHESESABLE_NH_CHARS_PATTERN.matcher( data ).find() ) {
1182                 sb.append( '\'' );
1183                 sb.append( data );
1184                 sb.append( '\'' );
1185             }
1186             else {
1187                 sb.append( data );
1188             }
1189         }
1190         return sb;
1191     }
1192
1193     public static boolean seqIsLikelyToBeAa( final String s ) {
1194         final String seq = s.toLowerCase();
1195         if ( ( seq.indexOf( 'r' ) > -1 ) || ( seq.indexOf( 'd' ) > -1 ) || ( seq.indexOf( 'e' ) > -1 )
1196                 || ( seq.indexOf( 'q' ) > -1 ) || ( seq.indexOf( 'h' ) > -1 ) || ( seq.indexOf( 'k' ) > -1 )
1197                 || ( seq.indexOf( 'w' ) > -1 ) || ( seq.indexOf( 's' ) > -1 ) || ( seq.indexOf( 'm' ) > -1 )
1198                 || ( seq.indexOf( 'p' ) > -1 ) || ( seq.indexOf( 'v' ) > -1 ) ) {
1199             return true;
1200         }
1201         return false;
1202     }
1203
1204     final public static String stringArrayToString( final String[] a ) {
1205         return stringArrayToString( a, ", " );
1206     }
1207
1208     final public static String stringArrayToString( final String[] a, final String separator ) {
1209         final StringBuilder sb = new StringBuilder();
1210         if ( ( a != null ) && ( a.length > 0 ) ) {
1211             for( int i = 0; i < ( a.length - 1 ); ++i ) {
1212                 sb.append( a[ i ] + separator );
1213             }
1214             sb.append( a[ a.length - 1 ] );
1215         }
1216         return sb.toString();
1217     }
1218
1219     final public static String[] stringListToArray( final List<String> list ) {
1220         if ( list != null ) {
1221             final String[] str = new String[ list.size() ];
1222             int i = 0;
1223             for( final String l : list ) {
1224                 str[ i++ ] = l;
1225             }
1226             return str;
1227         }
1228         return null;
1229     }
1230
1231     final public static String stringListToString( final List<String> l, final String separator ) {
1232         final StringBuilder sb = new StringBuilder();
1233         if ( ( l != null ) && ( l.size() > 0 ) ) {
1234             for( int i = 0; i < ( l.size() - 1 ); ++i ) {
1235                 sb.append( l.get( i ) + separator );
1236             }
1237             sb.append( l.get( l.size() - 1 ) );
1238         }
1239         return sb.toString();
1240     }
1241
1242     final public static String[] stringSetToArray( final Set<String> strings ) {
1243         final String[] str_array = new String[ strings.size() ];
1244         int i = 0;
1245         for( final String e : strings ) {
1246             str_array[ i++ ] = e;
1247         }
1248         return str_array;
1249     }
1250
1251     final public static void unexpectedFatalError( final Error e ) {
1252         System.err.println();
1253         System.err.println( "unexpected error: should not have occured! Please contact program author(s)." );
1254         e.printStackTrace( System.err );
1255         System.err.println();
1256         System.exit( -1 );
1257     }
1258
1259     final public static void unexpectedFatalError( final Exception e ) {
1260         System.err.println();
1261         System.err.println( "unexpected exception: should not have occured! Please contact program author(s)." );
1262         e.printStackTrace( System.err );
1263         System.err.println();
1264         System.exit( -1 );
1265     }
1266
1267     final public static void unexpectedFatalError( final String message ) {
1268         System.err.println();
1269         System.err.println( "unexpected error: should not have occured! Please contact program author(s)." );
1270         System.err.println( message );
1271         System.err.println();
1272         System.exit( -1 );
1273     }
1274
1275     final public static void unexpectedFatalError( final String prg_name, final Exception e ) {
1276         System.err.println();
1277         System.err.println( "[" + prg_name
1278                 + "] > unexpected error; should not have occured! Please contact program author(s)." );
1279         e.printStackTrace( System.err );
1280         System.err.println();
1281         System.exit( -1 );
1282     }
1283
1284     final public static void unexpectedFatalError( final String prg_name, final String message ) {
1285         System.err.println();
1286         System.err.println( "[" + prg_name
1287                 + "] > unexpected error: should not have occured! Please contact program author(s)." );
1288         System.err.println( message );
1289         System.err.println();
1290         System.exit( -1 );
1291     }
1292
1293     final public static void unexpectedFatalError( final String prg_name, final String message, final Exception e ) {
1294         System.err.println();
1295         System.err.println( "[" + prg_name
1296                 + "] > unexpected error: should not have occured! Please contact program author(s)." );
1297         System.err.println( message );
1298         e.printStackTrace( System.err );
1299         System.err.println();
1300         System.exit( -1 );
1301     }
1302
1303     public final static void updateProgress( final double progress_percentage ) {
1304         final int width = 50;
1305         System.out.print( "\r[" );
1306         int i = 0;
1307         for( ; i <= ForesterUtil.roundToInt( progress_percentage * width ); i++ ) {
1308             System.out.print( "." );
1309         }
1310         for( ; i < width; i++ ) {
1311             System.out.print( " " );
1312         }
1313         System.out.print( "]" );
1314     }
1315
1316     public final static void updateProgress( final int i, final DecimalFormat f ) {
1317         System.out.print( "\r[" + f.format( i ) + "]" );
1318     }
1319
1320     public final static String wordWrap( final String str, final int width ) {
1321         final StringBuilder sb = new StringBuilder( str );
1322         int start = 0;
1323         int ls = -1;
1324         int i = 0;
1325         while ( i < sb.length() ) {
1326             if ( sb.charAt( i ) == ' ' ) {
1327                 ls = i;
1328             }
1329             if ( sb.charAt( i ) == '\n' ) {
1330                 ls = -1;
1331                 start = i + 1;
1332             }
1333             if ( i > ( ( start + width ) - 1 ) ) {
1334                 if ( ls != -1 ) {
1335                     sb.setCharAt( ls, '\n' );
1336                     start = ls + 1;
1337                     ls = -1;
1338                 }
1339                 else {
1340                     sb.insert( i, '\n' );
1341                     start = i + 1;
1342                 }
1343             }
1344             i++;
1345         }
1346         return sb.toString();
1347     }
1348
1349     /**
1350      * Helper method for calcColor methods.
1351      * 
1352      * @param smallercolor_component_x
1353      *            color component the smaller color
1354      * @param largercolor_component_x
1355      *            color component the larger color
1356      * @param x
1357      *            factor
1358      * @return an int representing a color component
1359      */
1360     final private static int calculateColorComponent( final double smallercolor_component_x,
1361                                                       final double largercolor_component_x,
1362                                                       final double x ) {
1363         return ( int ) ( smallercolor_component_x + ( ( x * ( largercolor_component_x - smallercolor_component_x ) ) / 255.0 ) );
1364     }
1365
1366     /**
1367      * Helper method for calcColor methods.
1368      * 
1369      * 
1370      * @param value
1371      *            the value
1372      * @param larger
1373      *            the largest value
1374      * @param smaller
1375      *            the smallest value
1376      * @return a normalized value between larger and smaller
1377      */
1378     final private static double calculateColorFactor( final double value, final double larger, final double smaller ) {
1379         return ( 255.0 * ( value - smaller ) ) / ( larger - smaller );
1380     }
1381
1382     final private static String[] splitString( final String str ) {
1383         final String regex = "[\\s;,]+";
1384         return str.split( regex );
1385     }
1386 }