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 022package org.biojava.bio.seq.impl; 023 024import java.io.Serializable; 025import java.util.Collections; 026import java.util.Iterator; 027import java.util.List; 028 029import org.biojava.bio.Annotation; 030import org.biojava.bio.BioException; 031import org.biojava.bio.SimpleAnnotation; 032import org.biojava.bio.seq.Feature; 033import org.biojava.bio.seq.FeatureFilter; 034import org.biojava.bio.seq.FeatureHolder; 035import org.biojava.bio.seq.FeatureRealizer; 036import org.biojava.bio.seq.RealizingFeatureHolder; 037import org.biojava.bio.seq.Sequence; 038import org.biojava.bio.seq.SimpleFeatureHolder; 039import org.biojava.bio.symbol.Alphabet; 040import org.biojava.bio.symbol.Edit; 041import org.biojava.bio.symbol.Symbol; 042import org.biojava.bio.symbol.SymbolList; 043import org.biojava.utils.AbstractChangeable; 044import org.biojava.utils.ChangeEvent; 045import org.biojava.utils.ChangeListener; 046import org.biojava.utils.ChangeSupport; 047import org.biojava.utils.ChangeType; 048import org.biojava.utils.ChangeVetoException; 049 050/** 051 * A basic implementation of the <code>Sequence</code> interface. 052 * <p> 053 * This class now implements all methods in the SymbolList interface by 054 * delegating to another SymbolList object. This avoids unnecessary copying, but 055 * means that any changes in the underlying SymbolList will be silently 056 * reflected in the SimpleSequence. In general, SimpleSequences should 057 * <em>only</em> be constructed from SymbolLists which are known to be 058 * immutable. 059 * </p> 060 * 061 * <p> 062 * By default, features attached to a SimpleSequence are realized as simple 063 * in-memory implementations using <code>SimpleFeatureRealizer.DEFAULT</code>. 064 * If you need alternative feature realization behaviour, any 065 * <code>FeatureRealizer</code> implementation may be supplied at 066 * construction-time. 067 * </p> 068 * More functionality and better persistence to biosql is offered by 069 * {@link org.biojavax.bio.seq.SimpleRichSequence SimpleRichSequence} 070 * 071 * @author Matthew Pocock 072 * @author Thomas Down 073 * @author Mark Schreiber 074 * @serial WARNING serialized versions of this class may not be compatable with 075 * future versions of Biojava 076 */ 077public class SimpleSequence extends AbstractChangeable implements Sequence, 078 RealizingFeatureHolder, Serializable { 079 // 080 // This section is for the SymbolList implementation-by-delegation 081 // 082 083 private class FeatureForwarder implements ChangeListener { 084 public void postChange(ChangeEvent cev) { 085 ChangeSupport cs = getChangeSupport(cev.getType()); 086 synchronized (cs) { 087 cs.firePostChangeEvent(cev); 088 } 089 } 090 091 public void preChange(ChangeEvent cev) throws ChangeVetoException { 092 ChangeSupport cs = getChangeSupport(cev.getType()); 093 synchronized (cs) { 094 cs.firePreChangeEvent(cev); 095 } 096 } 097 } 098 /** 099 * 100 */ 101 private static final long serialVersionUID = -8681680737943980721L; 102 103 private Annotation annotation; 104 105 private transient ChangeListener featureForwarder; 106 107 private SimpleFeatureHolder featureHolder; 108 109 private transient FeatureRealizer featureRealizer; 110 111 private String name; 112 113 /** 114 * Delegate SymbolList. 115 */ 116 117 private SymbolList symList; 118 119 private String urn; 120 121 /** 122 * Create a SimpleSequence with the symbols and alphabet of sym, and the 123 * sequence properties listed. 124 * 125 * @param sym 126 * the SymbolList to wrap as a sequence 127 * @param urn 128 * the URN 129 * @param name 130 * the name - should be unique if practical 131 * @param annotation 132 * the annotation object to use or null 133 */ 134 public SimpleSequence(SymbolList sym, String urn, String name, 135 Annotation annotation) { 136 symList = sym; 137 138 setURN(urn); 139 setName(name); 140 this.annotation = annotation; 141 this.featureRealizer = FeatureImpl.DEFAULT; 142 } 143 144 // 145 // Extra stuff which is unique to Sequences 146 // 147 148 /** 149 * Create a SimpleSequence using a specified FeatureRealizer. 150 * 151 * @param sym 152 * the SymbolList to wrap as a sequence 153 * @param urn 154 * the URN 155 * @param name 156 * the name - should be unique if practical 157 * @param annotation 158 * the annotation object to use or null 159 * @param realizer 160 * the FeatureRealizer implemetation to use when adding features 161 */ 162 public SimpleSequence(SymbolList sym, String urn, String name, 163 Annotation annotation, FeatureRealizer realizer) { 164 symList = sym; 165 166 setURN(urn); 167 setName(name); 168 this.annotation = annotation; 169 this.featureRealizer = realizer; 170 } 171 public boolean containsFeature(Feature f) { 172 if (featureHolderAllocated()) { 173 return getFeatureHolder().containsFeature(f); 174 } else { 175 return false; 176 } 177 } 178 public int countFeatures() { 179 if (featureHolderAllocated()) 180 return getFeatureHolder().countFeatures(); 181 return 0; 182 } 183 public Feature createFeature(Feature.Template template) 184 throws BioException, ChangeVetoException { 185 Feature f = realizeFeature(this, template); 186 SimpleFeatureHolder fh = this.getFeatureHolder(); 187 synchronized (fh) { 188 fh.addFeature(f); 189 } 190 return f; 191 } 192 /** 193 * Create a new feature in any FeatureHolder associated with this sequence. 194 * 195 * @deprecated Please use new 1-arg createFeature instead. 196 */ 197 198 public Feature createFeature(FeatureHolder fh, Feature.Template template) 199 throws BioException, ChangeVetoException { 200 return fh.createFeature(template); 201 } 202 203 // private void readObject(ObjectInputStream s)throws IOException, 204 // ClassNotFoundException{ 205 // s.defaultReadObject(); 206 // this.featureRealizer = FeatureImpl.DEFAULT; 207 // } 208 209 public void edit(Edit edit) throws ChangeVetoException { 210 throw new ChangeVetoException("Can't edit the underlying SymbolList"); 211 } 212 213 protected boolean featureHolderAllocated() { 214 return featureHolder != null; 215 } 216 217 public Iterator<Feature> features() { 218 if (featureHolderAllocated()) 219 return getFeatureHolder().features(); 220 return Collections.EMPTY_LIST.iterator(); 221 } 222 223 public FeatureHolder filter(FeatureFilter filter) { 224 return getFeatureHolder().filter(filter); 225 } 226 227 public FeatureHolder filter(FeatureFilter ff, boolean recurse) { 228 if (featureHolderAllocated()) { 229 return getFeatureHolder().filter(ff, recurse); 230 } 231 return FeatureHolder.EMPTY_FEATURE_HOLDER; 232 } 233 234 public Alphabet getAlphabet() { 235 return symList.getAlphabet(); 236 } 237 238 public Annotation getAnnotation() { 239 if (annotation == null) 240 annotation = new SimpleAnnotation(); 241 return annotation; 242 } 243 244 protected ChangeSupport getChangeSupport(ChangeType ct) { 245 ChangeSupport changeSupport = super.getChangeSupport(ct); 246 247 if (featureForwarder == null && featureHolder != null) { 248 featureForwarder = new FeatureForwarder(); 249 featureHolder.addChangeListener(featureForwarder, 250 ChangeType.UNKNOWN); 251 } 252 253 return changeSupport; 254 } 255 256 protected SimpleFeatureHolder getFeatureHolder() { 257 if (featureHolder == null) { 258 featureHolder = new SimpleFeatureHolder(FeatureFilter.top_level); 259 } 260 return featureHolder; 261 } 262 263 public String getName() { 264 return name; 265 } 266 267 public FeatureFilter getSchema() { 268 return getFeatureHolder().getSchema(); 269 } 270 271 public String getURN() { 272 return urn; 273 } 274 275 public Iterator iterator() { 276 return symList.iterator(); 277 } 278 279 public int length() { 280 return symList.length(); 281 } 282 283 public Feature realizeFeature(FeatureHolder parent, 284 Feature.Template template) throws BioException { 285 return featureRealizer.realizeFeature(this, parent, template); 286 } 287 288 /** 289 * Remove a feature attached to this sequence. 290 */ 291 292 public void removeFeature(Feature f) throws ChangeVetoException, 293 BioException { 294 getFeatureHolder().removeFeature(f); 295 } 296 297 public String seqString() { 298 return symList.seqString(); 299 } 300 301 /** 302 *Assign a name to this sequence 303 */ 304 305 public void setName(String name) { 306 this.name = name; 307 } 308 309 /** 310 *Provide the URN for this sequence 311 */ 312 313 public void setURN(String urn) { 314 this.urn = urn; 315 } 316 317 public SymbolList subList(int start, int end) { 318 return symList.subList(start, end); 319 } 320 321 public String subStr(int start, int end) { 322 return symList.subStr(start, end); 323 } 324 325 // 326 // Changeable stuff 327 // 328 329 public Symbol symbolAt(int index) { 330 return symList.symbolAt(index); 331 } 332 333 public List toList() { 334 return symList.toList(); 335 } 336 337 public String toString() { 338 return super.toString() + " name: " + getName(); 339 } 340}