001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.bio.taxa; 022 023import org.biojava.bio.Annotatable; 024import org.biojava.bio.Annotation; 025import org.biojava.bio.SmallAnnotation; 026import org.biojava.utils.AbstractChangeable; 027import org.biojava.utils.ChangeEvent; 028import org.biojava.utils.ChangeForwarder; 029import org.biojava.utils.ChangeListener; 030import org.biojava.utils.ChangeSupport; 031import org.biojava.utils.ChangeType; 032import org.biojava.utils.ChangeVetoException; 033 034/** 035 * <p>An abstract implementation of Taxon.</p> 036 * 037 * <p>It is left up to the impementor to provide methods for accessing the 038 * parent and children. All other state is provided for here. A common pattern 039 * would be to route any Taxon.getParent() call back via a method on the 040 * TaxonFactory used to generate this instance.</p> 041 * 042 * @author Matthew Pocock 043 * @author Keith James 044 * @since 1.3 045 * @deprecated replaced by classes in {@link org.biojavax.bio.taxa org.biojavax.bio.taxa} 046 */ 047public abstract class AbstractTaxon 048 extends 049 AbstractChangeable 050 implements 051 Taxon 052{ 053 private transient ChangeListener annotationForwarder; 054 private Annotation ann; 055 private String commonName; 056 private String scientificName; 057 058 protected AbstractTaxon() {} 059 060 protected AbstractTaxon(String scientificName, String commonName) { 061 this.scientificName = scientificName; 062 this.commonName = commonName; 063 } 064 065 // ensure that change support gubbins gets wired in for the annotation object. 066 protected ChangeSupport getChangeSupport(ChangeType ct) { 067 ChangeSupport cs = super.getChangeSupport(ct); 068 069 if( 070 (annotationForwarder == null) && 071 (ct == null || ct == Annotatable.ANNOTATION) 072 ) { 073 annotationForwarder = 074 new ChangeForwarder.Retyper(this, cs, Annotation.PROPERTY); 075 getAnnotation().addChangeListener( 076 annotationForwarder, 077 Annotatable.ANNOTATION 078 ); 079 } 080 081 return cs; 082 } 083 084 public String getCommonName() { 085 return commonName; 086 } 087 088 public void setCommonName(String commonName) 089 throws 090 ChangeVetoException 091 { 092 if(this.commonName != null) { 093 throw new ChangeVetoException( 094 "Common name already set to: " + 095 this.commonName + 096 " so you can't set it to: " + 097 commonName 098 ); 099 } 100 101 if(hasListeners()) { 102 ChangeSupport cs = getChangeSupport(Taxon.CHANGE_COMMON_NAME); 103 ChangeEvent cevt = new ChangeEvent(this, Taxon.CHANGE_COMMON_NAME, commonName); 104 synchronized(cs) { 105 cs.firePreChangeEvent(cevt); 106 this.commonName = commonName; 107 cs.firePostChangeEvent(cevt); 108 } 109 } else { 110 this.commonName = commonName; 111 } 112 } 113 114 public String getScientificName() { 115 return scientificName; 116 } 117 118 public void setScientificName(String scientificName) 119 throws 120 ChangeVetoException 121 { 122 if(this.scientificName != null) { 123 throw new ChangeVetoException( 124 "Common name already set to: " + 125 this.scientificName + 126 " so you can't set it to: " + 127 scientificName 128 ); 129 } 130 131 if(hasListeners()) { 132 ChangeSupport cs = getChangeSupport(Taxon.CHANGE_SCIENTIFIC_NAME); 133 ChangeEvent cevt = new ChangeEvent(this, Taxon.CHANGE_SCIENTIFIC_NAME, scientificName); 134 synchronized(cs) { 135 cs.firePreChangeEvent(cevt); 136 this.scientificName = scientificName; 137 cs.firePostChangeEvent(cevt); 138 } 139 } else { 140 this.scientificName = scientificName; 141 } 142 } 143 144 public Annotation getAnnotation() { 145 if(ann == null) { 146 ann = new SmallAnnotation(); 147 } 148 149 return ann; 150 } 151 152 public boolean equals(Object o) { 153 if(o instanceof Taxon) { 154 Taxon t = (Taxon) o; 155 156 return 157 this == t || ( 158 safeEq(this.getScientificName(), t.getScientificName()) && 159 safeEq(this.getCommonName(), t.getCommonName()) && 160 safeEq(this.getChildren(), t.getChildren()) 161 ); 162 } 163 164 return false; 165 } 166 167 public String toString() { 168 Taxon parent = getParent(); 169 String scientificName = getScientificName(); 170 171 if(parent != null) { 172 return parent.toString() + " -> " + scientificName; 173 } else { 174 return scientificName; 175 } 176 } 177 178 public int hashCode() { 179 return getScientificName().hashCode(); 180 } 181 182 private boolean safeEq(Object a, Object b) { 183 if(a == null && b == null) { 184 return true; 185 } else if(a == null || b == null) { 186 return false; 187 } else { 188 return a.equals(b); 189 } 190 } 191} 192