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