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 */ 021 022 023package org.biojava.bio.symbol; 024 025import java.io.Serializable; 026import java.util.HashSet; 027import java.util.Iterator; 028import java.util.List; 029import java.util.Set; 030 031import org.biojava.bio.Annotatable; 032import org.biojava.bio.Annotation; 033import org.biojava.bio.SimpleAnnotation; 034import org.biojava.utils.ChangeEvent; 035import org.biojava.utils.ChangeForwarder; 036import org.biojava.utils.ChangeSupport; 037import org.biojava.utils.ChangeType; 038import org.biojava.utils.ChangeVetoException; 039import org.biojava.utils.SingletonList; 040 041/** 042 * A simple no-frills implementation of the FiniteAlphabet interface. 043 * 044 * @serial WARNING the serialized version of this class may not be compatible with future versions 045 * @author Matthew Pocock 046 */ 047public class SimpleAlphabet 048extends AbstractAlphabet 049implements Serializable { 050 private String name; 051 private Annotation annotation; 052 private final Set symbols; 053 protected transient ChangeForwarder annotationForwarder; 054 055 //BE SURE TO CHANGE THIS VALUE IF YOU CHANGE THE IMPLEMENTATION 056 //SUCH THAT SERIALIZATION WILL FAIL. 057 private static final long serialVersionUID = 216254146; 058 059 /** 060 * A list of alphabets that make up this one - a singleton list containing 061 * this. 062 */ 063 private List alphabets; 064 065 public Iterator iterator() { 066 return symbols.iterator(); 067 } 068 069 public String getName() { 070 return name; 071 } 072 073 /** 074 * Assign a name to the alphabet 075 * @param name the name you wish to give this alphabet 076 */ 077 public void setName(String name) { 078 this.name = name; 079 } 080 081 public Annotation getAnnotation() { 082 if(annotation == null) 083 annotation = new SimpleAnnotation(); 084 return annotation; 085 } 086 087 public int size() { 088 return symbols.size(); 089 } 090 091 protected boolean containsImpl(AtomicSymbol s) { 092 return symbols.contains(s); 093 } 094 095 protected void addSymbolImpl(AtomicSymbol s) 096 throws IllegalSymbolException, ChangeVetoException { 097 symbols.add(s); 098 } 099 100 public void removeSymbol(Symbol s) 101 throws IllegalSymbolException { 102 validate(s); 103 //change checking should probably happen in AbstractAlphabet but oh well. 104 if(hasListeners(Alphabet.SYMBOLS)) { 105 ChangeSupport cs = getChangeSupport(Alphabet.SYMBOLS); 106 synchronized(cs) { 107 ChangeEvent ce = new ChangeEvent(this, Alphabet.SYMBOLS, null, s); 108 cs.firePreChangeEvent(ce); 109 _removeSymbol(s); 110 cs.firePostChangeEvent(ce); 111 } 112 }else{ 113 _removeSymbol(s); 114 } 115 } 116 117 private void _removeSymbol(final Symbol s) { 118 119 if(s instanceof AtomicSymbol) { 120 symbols.remove(s); 121 } else { 122 FiniteAlphabet sa = (FiniteAlphabet) s.getMatches(); 123 Iterator i = sa.iterator(); 124 while(i.hasNext()) { 125 Symbol sym = (Symbol) i.next(); 126 symbols.remove(sym); 127 } 128 } 129 } 130 131 public List getAlphabets() { 132 if(this.alphabets == null) { 133 this.alphabets = new SingletonList(this); 134 } 135 return this.alphabets; 136 } 137 138 protected AtomicSymbol getSymbolImpl(List symL) 139 throws IllegalSymbolException { 140 AtomicSymbol s = (AtomicSymbol) symL.get(0); 141 return s; 142 } 143 144 public SimpleAlphabet() { 145 this(new HashSet(), null); 146 } 147 148 public SimpleAlphabet(Set symbols) { 149 this(symbols, null); 150 } 151 152 public SimpleAlphabet(String name) { 153 this(new HashSet(), name); 154 } 155 156 public SimpleAlphabet(Set symbols, String name) { 157 this.symbols = new HashSet(); 158 this.name = name; 159 this.alphabets = null; 160 161 // this costs, but I am tracking down a ClassCast exception. 162 // roll on parameterised types. 163 for(Iterator i = symbols.iterator(); i.hasNext(); ) { 164 AtomicSymbol a = (AtomicSymbol) i.next(); 165 this.symbols.add(a); 166 } 167 } 168 169 protected ChangeSupport getChangeSupport(ChangeType ct){ 170 ChangeSupport cs = super.getChangeSupport(ct); 171 172 if(annotationForwarder == null && 173 (ct.isMatchingType(Annotatable.ANNOTATION) || Annotatable.ANNOTATION.isMatchingType(ct))) 174 { 175 annotationForwarder = 176 new ChangeForwarder.Retyper(this, cs, Annotation.PROPERTY); 177 getAnnotation().addChangeListener( 178 annotationForwarder, 179 Annotatable.ANNOTATION); 180 } 181 return cs; 182 } 183 184}