+ public final boolean hasNext() {
+ return _next != null;
+ }
+
+ @Override
+ public final Phylogeny next() throws NHXFormatException, IOException {
+ final Phylogeny phy = _next;
+ parseNext();
+ return phy;
+ }
+
+ @Override
+ public final Phylogeny[] parse() throws IOException {
+ final List<Phylogeny> l = new ArrayList<Phylogeny>();
+ while ( hasNext() ) {
+ l.add( next() );
+ }
+ final Phylogeny[] p = new Phylogeny[ l.size() ];
+ for( int i = 0; i < l.size(); ++i ) {
+ p[ i ] = l.get( i );
+ }
+ reset();
+ return p;
+ }
+
+ @Override
+ public final void reset() throws NHXFormatException, IOException {
+ _i = 0;
+ _next = null;
+ _in_comment = false;
+ _saw_colon = false;
+ _saw_open_bracket = false;
+ _in_open_bracket = false;
+ _in_double_quote = false;
+ _in_single_quote = false;
+ _clade_level = 0;
+ _current_anotation = new StringBuilder();
+ _current_phylogeny = null;
+ _current_node = null;
+ _my_source_charary = null;
+ determineAndProcessSourceType( _source );
+ switch ( _input_type ) {
+ case CHAR_ARRAY:
+ _my_source_br = null;
+ _my_source_charary = ( char[] ) _nhx_source;
+ break;
+ case BUFFERED_READER:
+ _my_source_br = ( BufferedReader ) _nhx_source;
+ break;
+ default:
+ throw new RuntimeException( "unknown input type" );
+ }
+ parseNext();
+ }
+
+ public final void setGuessRootedness( final boolean guess_rootedness ) {
+ _guess_rootedness = guess_rootedness;
+ }
+
+ public final void setIgnoreQuotes( final boolean ignore_quotes ) {
+ _ignore_quotes = ignore_quotes;
+ }
+
+ public final void setReplaceUnderscores( final boolean replace_underscores ) {
+ _replace_underscores = replace_underscores;
+ }
+
+ @Override
+ public final void setSource( final Object nhx_source ) throws NHXFormatException, IOException {
+ _source = nhx_source;
+ reset();
+ }
+
+ public final void setTaxonomyExtraction( final TAXONOMY_EXTRACTION taxonomy_extraction ) {
+ _taxonomy_extraction = taxonomy_extraction;
+ }
+
+ public final void setAllowErrorsInDistanceToParent( final boolean allow_errors_in_distance_to_parent ) {
+ _allow_errors_in_distance_to_parent = allow_errors_in_distance_to_parent;
+ }
+
+ private final void determineAndProcessSourceType( final Object nhx_source ) throws IOException {
+ if ( nhx_source == null ) {
+ throw new PhylogenyParserException( getClass() + ": attempt to parse null object." );
+ }
+ else if ( nhx_source instanceof String ) {
+ _nhx_source = nhx_source;
+ _input_type = NHXParser.BUFFERED_READER;
+ _source_length = 0;
+ InputStream is = new ByteArrayInputStream( (( String ) nhx_source ).getBytes(getEncoding()));
+ final InputStreamReader isr = new InputStreamReader( is, getEncoding() );
+ _nhx_source = new BufferedReader( isr );
+ }
+ else if ( nhx_source instanceof char[] ) {
+ _input_type = NHXParser.CHAR_ARRAY;
+ _source_length = ( ( char[] ) nhx_source ).length;
+ _nhx_source = nhx_source;
+ }
+ else if ( nhx_source instanceof File ) {
+ _input_type = NHXParser.BUFFERED_READER;
+ _source_length = 0;
+ if ( _my_source_br != null ) {
+ //I am REALLY not sure if it is a "good" idea NOT to close the stream...
+ // try {
+ // _my_source_br.close();
+ // }
+ // catch ( final IOException e ) {
+ // }
+ }
+ final File f = ( File ) nhx_source;
+ final String error = ForesterUtil.isReadableFile( f );
+ if ( !ForesterUtil.isEmpty( error ) ) {
+ throw new PhylogenyParserException( error );
+ }
+ final InputStream is = new FileInputStream( f );
+ final InputStreamReader isr = new InputStreamReader( is, getEncoding() );
+ _nhx_source = new BufferedReader( isr );
+ }
+ else if ( nhx_source instanceof URL ) {
+ _input_type = NHXParser.BUFFERED_READER;
+ _source_length = 0;
+ if ( _my_source_br != null ) {
+ //I am REALLY not sure if it is a "good" idea NOT to close the stream...
+ // try {
+ // _my_source_br.close();
+ // }
+ // catch ( final IOException e ) {
+ // }
+ }
+ final InputStream is = ( ( URL ) nhx_source ).openStream();
+ final InputStreamReader isr = new InputStreamReader( is, getEncoding() );
+ _nhx_source = new BufferedReader( isr );
+ }
+ else if ( nhx_source instanceof InputStream ) {
+ _input_type = NHXParser.BUFFERED_READER;
+ _source_length = 0;
+ if ( _my_source_br != null ) {
+ //I am REALLY not sure if it is a "good" idea NOT to close the stream...
+ // try {
+ // _my_source_br.close();
+ // }
+ // catch ( final IOException e ) {
+ // }
+ }
+ final InputStream is = ( InputStream ) nhx_source;
+ final InputStreamReader isr = new InputStreamReader( is, getEncoding() );
+ _nhx_source = new BufferedReader( isr );
+ }
+ else {
+ throw new IllegalArgumentException( getClass() + " can only parse objects of type String,"
+ + " char[], File, InputStream, or URL "
+ + " [attempt to parse object of " + nhx_source.getClass() + "]." );
+ }
+ }
+
+ private final Phylogeny finishPhylogeny() throws PhylogenyParserException, NHXFormatException,
+ PhyloXmlDataFormatException {
+ if ( _current_phylogeny != null ) {
+ parseNHX( _current_anotation != null ? _current_anotation.toString() : "",
+ _current_phylogeny.getRoot(),
+ getTaxonomyExtraction(),
+ isReplaceUnderscores(),
+ isAllowErrorsInDistanceToParent(),
+ true,
+ isParseBeastStyleExtendedTags());
+ if ( GUESS_IF_SUPPORT_VALUES ) {
+ if ( isBranchLengthsLikeBootstrapValues( _current_phylogeny ) ) {
+ moveBranchLengthsToConfidenceValues( _current_phylogeny );
+ }
+ }
+ if ( isGuessRootedness() ) {
+ final PhylogenyNode root = _current_phylogeny.getRoot();
+ if ( ( root.getDistanceToParent() >= 0.0 ) || !ForesterUtil.isEmpty( root.getName() )
+ || !ForesterUtil.isEmpty( PhylogenyMethods.getSpecies( root ) ) || root.isHasAssignedEvent() ) {
+ _current_phylogeny.setRooted( true );
+ }
+ }
+ return _current_phylogeny;
+ }
+ return null;
+ }
+
+ private final Phylogeny finishSingleNodePhylogeny() throws PhylogenyParserException, NHXFormatException,
+ PhyloXmlDataFormatException {
+ final PhylogenyNode new_node = new PhylogenyNode();
+ parseNHX( _current_anotation.toString(),
+ new_node,
+ getTaxonomyExtraction(),
+ isReplaceUnderscores(),
+ isAllowErrorsInDistanceToParent(),
+ true,
+ isParseBeastStyleExtendedTags());
+ _current_phylogeny = new Phylogeny();
+ _current_phylogeny.setRoot( new_node );
+ return _current_phylogeny;
+ }
+
+ private final void init() {
+ setTaxonomyExtraction( TAXONOMY_EXTRACTION.NO );
+ setReplaceUnderscores( REPLACE_UNDERSCORES_DEFAULT );
+ setGuessRootedness( GUESS_ROOTEDNESS_DEFAULT );
+ setIgnoreQuotes( IGNORE_QUOTES_DEFAULT );
+ setAllowErrorsInDistanceToParent( ALLOW_ERRORS_IN_DISTANCE_TO_PARENT_DEFAULT );
+ setParseBeastStyleExtendedTags( false );
+ }
+
+ private final boolean isAllowErrorsInDistanceToParent() {
+ return _allow_errors_in_distance_to_parent;
+ }
+
+ private final boolean isGuessRootedness() {
+ return _guess_rootedness;
+ }
+
+ private final boolean isIgnoreQuotes() {
+ return _ignore_quotes;
+ }
+
+ private final boolean isReplaceUnderscores() {
+ return _replace_underscores;
+ }
+
+ private final void parseNext() throws IOException, NHXFormatException {
+ if ( _source == null ) {
+ throw new IOException( "source is not set" );
+ }