2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
5 // Copyright (C) 2008-2009 Christian M. Zmasek
6 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
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.
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.
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
23 // Contact: phylosoft @ gmail . com
24 // WWW: www.phylosoft.org/forester
26 package org.forester.phylogeny.data;
28 import java.io.IOException;
29 import java.io.Writer;
30 import java.util.ArrayList;
31 import java.util.List;
33 import org.forester.io.parsers.nhx.NHXtags;
34 import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
35 import org.forester.io.parsers.phyloxml.PhyloXmlMapping;
36 import org.forester.io.parsers.phyloxml.PhyloXmlUtil;
37 import org.forester.util.ForesterUtil;
39 public class Taxonomy implements PhylogenyData, MultipleUris, Comparable<Taxonomy> {
41 private String _scientific_name;
42 private String _common_name;
43 private List<String> _synonyms;
44 private String _authority;
45 private Identifier _identifier;
46 private String _taxonomy_code;
48 private List<Uri> _uris;
49 private List<String> _lineage;
56 public StringBuffer asSimpleText() {
61 public Uri getUri( final int index ) {
62 return getUris().get( index );
66 public void addUri( final Uri uri ) {
67 if ( getUris() == null ) {
68 setUris( new ArrayList<Uri>() );
74 public StringBuffer asText() {
75 final StringBuffer sb = new StringBuffer();
76 if ( getIdentifier() != null ) {
78 sb.append( getIdentifier().asSimpleText() );
81 if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) ) {
82 if ( sb.length() > 0 ) {
86 sb.append( getTaxonomyCode() );
89 if ( !ForesterUtil.isEmpty( getScientificName() ) ) {
90 if ( sb.length() > 0 ) {
93 sb.append( getScientificName() );
94 if ( !ForesterUtil.isEmpty( getAuthority() ) ) {
96 sb.append( getAuthority() );
100 if ( !ForesterUtil.isEmpty( getCommonName() ) ) {
101 if ( sb.length() > 0 ) {
104 sb.append( getCommonName() );
110 public PhylogenyData copy() {
111 final Taxonomy t = new Taxonomy();
112 t.setTaxonomyCode( getTaxonomyCode() );
113 t.setScientificName( getScientificName() );
114 t.setCommonName( getCommonName() );
115 t.setAuthority( getAuthority() );
116 for( final String syn : getSynonyms() ) {
117 t.getSynonyms().add( syn );
119 if ( getIdentifier() != null ) {
120 t.setIdentifier( ( Identifier ) getIdentifier().copy() );
123 t.setIdentifier( null );
125 t.setRank( new String( getRank() ) );
126 if ( getUris() != null ) {
127 t.setUris( new ArrayList<Uri>() );
128 for( final Uri uri : getUris() ) {
130 t.getUris().add( uri );
134 if ( getLineage() != null ) {
135 t.setLineage( new ArrayList<String>() );
136 for( final String l : getLineage() ) {
138 t.getLineage().add( l );
146 public boolean equals( final Object o ) {
150 else if ( o == null ) {
153 else if ( o.getClass() != this.getClass() ) {
154 throw new IllegalArgumentException( "attempt to check [" + this.getClass() + "] equality to " + o + " ["
155 + o.getClass() + "]" );
158 return isEqual( ( Taxonomy ) o );
162 public String getAuthority() {
166 public String getCommonName() {
170 public Identifier getIdentifier() {
174 public String getRank() {
178 public String getScientificName() {
179 return _scientific_name;
182 public List<String> getSynonyms() {
183 if ( _synonyms == null ) {
184 _synonyms = new ArrayList<String>();
189 public String getTaxonomyCode() {
190 return _taxonomy_code;
194 public List<Uri> getUris() {
199 public int hashCode() {
200 if ( getIdentifier() != null ) {
201 return getIdentifier().hashCode();
203 else if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) ) {
204 return getTaxonomyCode().hashCode();
206 else if ( !ForesterUtil.isEmpty( getScientificName() ) ) {
207 if ( !ForesterUtil.isEmpty( getAuthority() ) ) {
208 return ( getScientificName().toLowerCase() + getAuthority().toLowerCase() ).hashCode();
210 return getScientificName().toLowerCase().hashCode();
213 return getCommonName().toLowerCase().hashCode();
218 setScientificName( "" );
220 setIdentifier( null );
222 setTaxonomyCode( "" );
229 public boolean isEmpty() {
230 return ( ( getIdentifier() == null ) && ForesterUtil.isEmpty( getTaxonomyCode() )
231 && ForesterUtil.isEmpty( getCommonName() ) && ForesterUtil.isEmpty( getScientificName() )
232 && ForesterUtil.isEmpty( getRank() ) && ForesterUtil.isEmpty( _uris )
233 && ForesterUtil.isEmpty( getAuthority() ) && ForesterUtil.isEmpty( _synonyms ) && ForesterUtil.isEmpty( _lineage ) );
238 * If this and taxonomy 'data' has an identifier, comparison will be based on that.
239 * Otherwise, if this and taxonomy 'data' has a code, comparison will be based on that.
240 * Otherwise, if Taxonomy 'data' has a scientific name, comparison will be
241 * based on that (case insensitive!).
242 * Otherwise, if Taxonomy 'data' has a common name, comparison will be
243 * based on that (case insensitive!).
244 * (Note. This is important and should not be change without a very good reason.)
248 public boolean isEqual( final PhylogenyData data ) {
249 if ( this == data ) {
252 final Taxonomy tax = ( Taxonomy ) data;
253 if ( ( getIdentifier() != null ) && ( tax.getIdentifier() != null ) ) {
254 return getIdentifier().isEqual( tax.getIdentifier() );
256 else if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) && !ForesterUtil.isEmpty( tax.getTaxonomyCode() ) ) {
257 return getTaxonomyCode().equals( tax.getTaxonomyCode() );
259 else if ( !ForesterUtil.isEmpty( getScientificName() ) && !ForesterUtil.isEmpty( tax.getScientificName() ) ) {
260 if ( !ForesterUtil.isEmpty( getAuthority() ) && !ForesterUtil.isEmpty( tax.getAuthority() ) ) {
261 return ( getScientificName().equalsIgnoreCase( tax.getScientificName() ) )
262 && ( getAuthority().equalsIgnoreCase( tax.getAuthority() ) );
264 return getScientificName().equalsIgnoreCase( tax.getScientificName() );
266 else if ( !ForesterUtil.isEmpty( getCommonName() ) && !ForesterUtil.isEmpty( tax.getCommonName() ) ) {
267 return getCommonName().equalsIgnoreCase( tax.getCommonName() );
269 else if ( !ForesterUtil.isEmpty( getScientificName() ) && !ForesterUtil.isEmpty( tax.getCommonName() ) ) {
270 return getScientificName().equalsIgnoreCase( tax.getCommonName() );
272 else if ( !ForesterUtil.isEmpty( getCommonName() ) && !ForesterUtil.isEmpty( tax.getScientificName() ) ) {
273 return getCommonName().equalsIgnoreCase( tax.getScientificName() );
275 throw new RuntimeException( "comparison not possible with empty fields" );
278 public void setAuthority( final String authority ) {
279 _authority = authority;
282 public void setCommonName( final String common_name ) {
283 _common_name = common_name;
286 public void setIdentifier( final Identifier identifier ) {
287 _identifier = identifier;
290 public void setRank( final String rank ) {
291 if ( !ForesterUtil.isEmpty( rank ) && !PhyloXmlUtil.TAXONOMY_RANKS.contains( rank ) ) {
292 throw new PhyloXmlDataFormatException( "illegal rank: [" + rank + "]" );
297 public void setScientificName( final String scientific_name ) {
298 _scientific_name = scientific_name;
301 private void setSynonyms( final List<String> synonyms ) {
302 _synonyms = synonyms;
305 public void setTaxonomyCode( final String taxonomy_code ) {
306 if ( !ForesterUtil.isEmpty( taxonomy_code )
307 && !PhyloXmlUtil.TAXOMONY_CODE_PATTERN.matcher( taxonomy_code ).matches() ) {
308 throw new PhyloXmlDataFormatException( "illegal taxonomy code: [" + taxonomy_code + "]" );
310 _taxonomy_code = taxonomy_code;
314 public void setUris( final List<Uri> uris ) {
319 public StringBuffer toNHX() {
320 final StringBuffer sb = new StringBuffer();
321 if ( getIdentifier() != null ) {
322 sb.append( ':' + NHXtags.TAXONOMY_ID );
323 sb.append( ForesterUtil.replaceIllegalNhxCharacters( getIdentifier().getValue() ) );
325 final StringBuffer species = new StringBuffer();
326 if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) ) {
327 species.append( ForesterUtil.replaceIllegalNhxCharacters( getTaxonomyCode() ) );
329 if ( !ForesterUtil.isEmpty( getScientificName() ) ) {
330 ForesterUtil.appendSeparatorIfNotEmpty( species, '|' );
331 species.append( ForesterUtil.replaceIllegalNhxCharacters( getScientificName() ) );
333 if ( !ForesterUtil.isEmpty( getCommonName() ) ) {
334 ForesterUtil.appendSeparatorIfNotEmpty( species, '|' );
335 species.append( ForesterUtil.replaceIllegalNhxCharacters( getCommonName() ) );
337 if ( species.length() > 0 ) {
338 sb.append( ':' + NHXtags.SPECIES_NAME );
339 sb.append( species );
345 public void toPhyloXML( final Writer writer, final int level, final String indentation ) throws IOException {
349 writer.write( ForesterUtil.LINE_SEPARATOR );
350 writer.write( indentation );
351 PhylogenyDataUtil.appendOpen( writer, PhyloXmlMapping.TAXONOMY );
352 if ( ( getIdentifier() != null ) && !ForesterUtil.isEmpty( getIdentifier().getValue() ) ) {
353 getIdentifier().toPhyloXML( writer, level, indentation );
355 if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) ) {
356 PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_CODE, getTaxonomyCode(), indentation );
358 if ( !ForesterUtil.isEmpty( getScientificName() ) ) {
359 PhylogenyDataUtil.appendElement( writer,
360 PhyloXmlMapping.TAXONOMY_SCIENTIFIC_NAME,
364 if ( !ForesterUtil.isEmpty( getAuthority() ) ) {
365 PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_AUTHORITY, getAuthority(), indentation );
367 if ( !ForesterUtil.isEmpty( getCommonName() ) ) {
369 .appendElement( writer, PhyloXmlMapping.TAXONOMY_COMMON_NAME, getCommonName(), indentation );
371 if ( _synonyms != null ) {
372 for( final String syn : getSynonyms() ) {
373 if ( !ForesterUtil.isEmpty( syn ) ) {
374 PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_SYNONYM, syn, indentation );
378 if ( !ForesterUtil.isEmpty( getRank() ) ) {
379 PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.TAXONOMY_RANK, getRank(), indentation );
381 if ( getUris() != null ) {
382 for( final Uri uri : getUris() ) {
384 uri.toPhyloXML( writer, level, indentation );
388 writer.write( ForesterUtil.LINE_SEPARATOR );
389 writer.write( indentation );
390 PhylogenyDataUtil.appendClose( writer, PhyloXmlMapping.TAXONOMY );
394 public String toString() {
395 return asText().toString();
399 public int compareTo( final Taxonomy o ) {
403 else if ( !ForesterUtil.isEmpty( getScientificName() ) && !ForesterUtil.isEmpty( o.getScientificName() ) ) {
404 return getScientificName().compareToIgnoreCase( o.getScientificName() );
406 else if ( !ForesterUtil.isEmpty( getCommonName() ) && !ForesterUtil.isEmpty( o.getCommonName() ) ) {
407 return getCommonName().compareToIgnoreCase( o.getCommonName() );
409 else if ( !ForesterUtil.isEmpty( getTaxonomyCode() ) && !ForesterUtil.isEmpty( o.getTaxonomyCode() ) ) {
410 return getTaxonomyCode().compareToIgnoreCase( o.getTaxonomyCode() );
415 public void setLineage( List<String> lineage ) {
419 public List<String> getLineage() {