// $Id: Taxonomy.java,v 1.58 2010/09/23 00:21:24 cmzmasek Exp $ // FORESTER -- software libraries and applications // for evolutionary biology research and applications. // // Copyright (C) 2008-2009 Christian M. Zmasek // Copyright (C) 2008-2009 Burnham Institute for Medical Research // All rights reserved // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA // // Contact: cmzmasek@yahoo.com // WWW: www.phylosoft.org/forester package org.forester.phylogeny.data; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.List; import org.forester.io.parsers.nhx.NHXtags; import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException; import org.forester.io.parsers.phyloxml.PhyloXmlMapping; import org.forester.io.parsers.phyloxml.PhyloXmlUtil; import org.forester.util.ForesterUtil; public class Taxonomy implements PhylogenyData, Comparable<Taxonomy> { private String _scientific_name; private String _common_name; private List<String> _synonyms; private String _authority; private Identifier _identifier; private String _taxonomy_code; private String _rank; private Uri _uri; public Taxonomy() { init(); } public StringBuffer asSimpleText() { return asText(); } public StringBuffer asText() { final StringBuffer sb = new StringBuffer(); if ( getIdentifier() != null ) { sb.append( "[" ); sb.append( getIdentifier().asSimpleText() ); sb.append( "]" ); } if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) ) { if ( sb.length() > 0 ) { sb.append( " " ); } sb.append( "[" ); sb.append( getTaxonomyCode() ); sb.append( "]" ); } if ( !ForesterUtil.isEmpty( getScientificName() ) ) { if ( sb.length() > 0 ) { sb.append( " " ); } sb.append( getScientificName() ); if ( !ForesterUtil.isEmpty( getAuthority() ) ) { sb.append( " (" ); sb.append( getAuthority() ); sb.append( ")" ); } } if ( !ForesterUtil.isEmpty( getCommonName() ) ) { if ( sb.length() > 0 ) { sb.append( " " ); } sb.append( getCommonName() ); } return sb; } public PhylogenyData copy() { final Taxonomy t = new Taxonomy(); t.setTaxonomyCode( new String( getTaxonomyCode() ) ); t.setScientificName( new String( getScientificName() ) ); t.setCommonName( new String( getCommonName() ) ); t.setAuthority( new String( getAuthority() ) ); for( final String syn : getSynonyms() ) { t.getSynonyms().add( new String( syn ) ); } if ( getIdentifier() != null ) { t.setIdentifier( ( Identifier ) getIdentifier().copy() ); } else { t.setIdentifier( null ); } t.setRank( new String( getRank() ) ); if ( getUri() != null ) { t.setUri( ( Uri ) getUri().copy() ); } else { t.setUri( null ); } return t; } @Override public boolean equals( final Object o ) { if ( this == o ) { return true; } else if ( o == null ) { return false; } else if ( o.getClass() != this.getClass() ) { throw new IllegalArgumentException( "attempt to check [" + this.getClass() + "] equality to " + o + " [" + o.getClass() + "]" ); } else { return isEqual( ( Taxonomy ) o ); } } public String getAuthority() { return _authority; } public String getCommonName() { return _common_name; } public Identifier getIdentifier() { return _identifier; } public String getRank() { return _rank; } public String getScientificName() { return _scientific_name; } public List<String> getSynonyms() { return _synonyms; } public String getTaxonomyCode() { return _taxonomy_code; } public Uri getUri() { return _uri; } @Override public int hashCode() { if ( getIdentifier() != null ) { return getIdentifier().hashCode(); } else if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) ) { return getTaxonomyCode().hashCode(); } else if ( !ForesterUtil.isEmpty( getScientificName() ) ) { if ( !ForesterUtil.isEmpty( getAuthority() ) ) { return ( getScientificName().toLowerCase() + getAuthority().toLowerCase() ).hashCode(); } return getScientificName().toLowerCase().hashCode(); } else { return getCommonName().toLowerCase().hashCode(); } } public void init() { setScientificName( "" ); setCommonName( "" ); setIdentifier( null ); setRank( "" ); setTaxonomyCode( "" ); setAuthority( "" ); setSynonyms( new ArrayList<String>() ); setUri( null ); } public boolean isEmpty() { return ( ( getIdentifier() == null ) && ForesterUtil.isEmpty( getTaxonomyCode() ) && ForesterUtil.isEmpty( getCommonName() ) && ForesterUtil.isEmpty( getScientificName() ) && ForesterUtil.isEmpty( getRank() ) && ( getUri() == null ) && ForesterUtil.isEmpty( getAuthority() ) && ( getSynonyms() .size() < 1 ) ); } /** * * If this and taxonomy 'data' has an identifier, comparison will be based on that. * Otherwise, if this and taxonomy 'data' has a code, comparison will be based on that. * Otherwise, if Taxonomy 'data' has a scientific name, comparison will be * based on that (case insensitive!). * Otherwise, if Taxonomy 'data' has a common name, comparison will be * based on that (case insensitive!). * (Note. This is important and should not be change without a very good reason.) * */ public boolean isEqual( final PhylogenyData data ) { if ( this == data ) { return true; } final Taxonomy tax = ( Taxonomy ) data; if ( ( getIdentifier() != null ) && ( tax.getIdentifier() != null ) ) { return getIdentifier().isEqual( tax.getIdentifier() ); } else if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) && !ForesterUtil.isEmpty( tax.getTaxonomyCode() ) ) { return getTaxonomyCode().equals( tax.getTaxonomyCode() ); } else if ( !ForesterUtil.isEmpty( getScientificName() ) && !ForesterUtil.isEmpty( tax.getScientificName() ) ) { if ( !ForesterUtil.isEmpty( getAuthority() ) && !ForesterUtil.isEmpty( tax.getAuthority() ) ) { return ( getScientificName().equalsIgnoreCase( tax.getScientificName() ) ) && ( getAuthority().equalsIgnoreCase( tax.getAuthority() ) ); } return getScientificName().equalsIgnoreCase( tax.getScientificName() ); } else if ( !ForesterUtil.isEmpty( getCommonName() ) && !ForesterUtil.isEmpty( tax.getCommonName() ) ) { return getCommonName().equalsIgnoreCase( tax.getCommonName() ); } else if ( !ForesterUtil.isEmpty( getScientificName() ) && !ForesterUtil.isEmpty( tax.getCommonName() ) ) { return getScientificName().equalsIgnoreCase( tax.getCommonName() ); } else if ( !ForesterUtil.isEmpty( getCommonName() ) && !ForesterUtil.isEmpty( tax.getScientificName() ) ) { return getCommonName().equalsIgnoreCase( tax.getScientificName() ); } throw new IllegalStateException( "comparison not possible with empty fields" ); } public void setAuthority( final String authority ) { _authority = authority; } public void setCommonName( final String common_name ) { _common_name = common_name; } public void setIdentifier( final Identifier identifier ) { _identifier = identifier; } public void setRank( final String rank ) { if ( !ForesterUtil.isEmpty( rank ) && !PhyloXmlUtil.TAXONOMY_RANKS.contains( rank ) ) { throw new PhyloXmlDataFormatException( "illegal rank: [" + rank + "]" ); } _rank = rank; } public void setScientificName( final String scientific_name ) { _scientific_name = scientific_name; } private void setSynonyms( final List<String> synonyms ) { _synonyms = synonyms; } public void setTaxonomyCode( final String taxonomy_code ) { if ( !ForesterUtil.isEmpty( taxonomy_code ) && !PhyloXmlUtil.TAXOMONY_CODE_PATTERN.matcher( taxonomy_code ).matches() ) { throw new PhyloXmlDataFormatException( "illegal taxonomy code: [" + taxonomy_code + "]" ); } _taxonomy_code = taxonomy_code; } public void setUri( final Uri uri ) { _uri = uri; } public StringBuffer toNHX() { final StringBuffer sb = new StringBuffer(); if ( getIdentifier() != null ) { sb.append( ':' + NHXtags.TAXONOMY_ID ); sb.append( ForesterUtil.replaceIllegalNhxCharacters( getIdentifier().getValue() ) ); } final StringBuffer species = new StringBuffer(); if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) ) { species.append( ForesterUtil.replaceIllegalNhxCharacters( getTaxonomyCode() ) ); } if ( !ForesterUtil.isEmpty( getScientificName() ) ) { ForesterUtil.appendSeparatorIfNotEmpty( species, '|' ); species.append( ForesterUtil.replaceIllegalNhxCharacters( getScientificName() ) ); } if ( !ForesterUtil.isEmpty( getCommonName() ) ) { ForesterUtil.appendSeparatorIfNotEmpty( species, '|' ); species.append( ForesterUtil.replaceIllegalNhxCharacters( getCommonName() ) ); } if ( species.length() > 0 ) { sb.append( ':' + NHXtags.SPECIES_NAME ); sb.append( species ); } return sb; } public void toPhyloXML( final Writer writer, final int level, final String indentation ) throws IOException { if ( isEmpty() ) { return; } writer.write( ForesterUtil.LINE_SEPARATOR ); writer.write( indentation ); PhylogenyDataUtil.appendOpen( writer, PhyloXmlMapping.TAXONOMY ); if ( ( getIdentifier() != null ) && !ForesterUtil.isEmpty( getIdentifier().getValue() ) ) { getIdentifier().toPhyloXML( writer, level, indentation ); } if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) ) { PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_CODE, getTaxonomyCode(), indentation ); } if ( !ForesterUtil.isEmpty( getScientificName() ) ) { PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_SCIENTIFIC_NAME, getScientificName(), indentation ); } if ( !ForesterUtil.isEmpty( getAuthority() ) ) { PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_AUTHORITY, getAuthority(), indentation ); } if ( !ForesterUtil.isEmpty( getCommonName() ) ) { PhylogenyDataUtil .appendElement( writer, PhyloXmlMapping.TAXONOMY_COMMON_NAME, getCommonName(), indentation ); } for( final String syn : getSynonyms() ) { if ( !ForesterUtil.isEmpty( syn ) ) { PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_SYNONYM, syn, indentation ); } } if ( !ForesterUtil.isEmpty( getRank() ) ) { PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_RANK, getRank(), indentation ); } if ( getUri() != null ) { getUri().toPhyloXML( writer, level, indentation ); } writer.write( ForesterUtil.LINE_SEPARATOR ); writer.write( indentation ); PhylogenyDataUtil.appendClose( writer, PhyloXmlMapping.TAXONOMY ); } @Override public String toString() { return asText().toString(); } @Override public int compareTo( final Taxonomy o ) { if ( isEqual( o ) ) { return 0; } else if ( !ForesterUtil.isEmpty( getScientificName() ) && !ForesterUtil.isEmpty( o.getScientificName() ) ) { return getScientificName().compareToIgnoreCase( o.getScientificName() ); } else if ( !ForesterUtil.isEmpty( getCommonName() ) && !ForesterUtil.isEmpty( o.getCommonName() ) ) { return getCommonName().compareToIgnoreCase( o.getCommonName() ); } else if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) && !ForesterUtil.isEmpty( o.getTaxonomyCode() ) ) { return getTaxonomyCode().compareToIgnoreCase( o.getTaxonomyCode() ); } return 0; } }