/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.bio.seq.impl; import java.io.Serializable; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.biojava.bio.Annotation; import org.biojava.bio.BioException; import org.biojava.bio.SimpleAnnotation; import org.biojava.bio.seq.Feature; import org.biojava.bio.seq.FeatureFilter; import org.biojava.bio.seq.FeatureHolder; import org.biojava.bio.seq.FeatureRealizer; import org.biojava.bio.seq.RealizingFeatureHolder; import org.biojava.bio.seq.Sequence; import org.biojava.bio.seq.SimpleFeatureHolder; import org.biojava.bio.symbol.Alphabet; import org.biojava.bio.symbol.Edit; import org.biojava.bio.symbol.Symbol; import org.biojava.bio.symbol.SymbolList; import org.biojava.utils.AbstractChangeable; import org.biojava.utils.ChangeEvent; import org.biojava.utils.ChangeListener; import org.biojava.utils.ChangeSupport; import org.biojava.utils.ChangeType; import org.biojava.utils.ChangeVetoException; /** * A basic implementation of the Sequence interface. *

* This class now implements all methods in the SymbolList * interface by delegating to another SymbolList object. This * avoids unnecessary copying, but means that any changes in * the underlying SymbolList will be silently reflected in * the SimpleSequence. In general, SimpleSequences should only * be constructed from SymbolLists which are known to be immutable. *

* *

* By default, features attached to a SimpleSequence are * realized as simple in-memory implementations using * SimpleFeatureRealizer.DEFAULT. If you need * alternative feature realization behaviour, any * FeatureRealizer implementation may be * supplied at construction-time. *

* More functionality and better persistence to biosql is offered by * {@link org.biojavax.bio.seq.SimpleRichSequence SimpleRichSequence} * * @author Matthew Pocock * @author Thomas Down * @author Mark Schreiber * @serial WARNING serialized versions of this class may not be compatable with future versions of Biojava */ public class SimpleSequence extends AbstractChangeable implements Sequence, RealizingFeatureHolder, Serializable { // // This section is for the SymbolList implementation-by-delegation // /** * Delegate SymbolList. */ private SymbolList symList; public Alphabet getAlphabet() { return symList.getAlphabet(); } public Iterator iterator() { return symList.iterator(); } public int length() { return symList.length(); } public String seqString() { return symList.seqString(); } public String subStr(int start, int end) { return symList.subStr(start, end); } public SymbolList subList(int start, int end) { return symList.subList(start, end); } public Symbol symbolAt(int index) { return symList.symbolAt(index); } public List toList() { return symList.toList(); } // // Extra stuff which is unique to Sequences // private String urn; private String name; private Annotation annotation; private SimpleFeatureHolder featureHolder; private transient FeatureRealizer featureRealizer; // private void readObject(ObjectInputStream s)throws IOException, ClassNotFoundException{ // s.defaultReadObject(); // this.featureRealizer = FeatureImpl.DEFAULT; // } protected SimpleFeatureHolder getFeatureHolder() { if(featureHolder == null) { featureHolder = new SimpleFeatureHolder(FeatureFilter.top_level); } return featureHolder; } protected boolean featureHolderAllocated() { return featureHolder != null; } public String getURN() { return urn; } /** *Provide the URN for this sequence */ public void setURN(String urn) { this.urn = urn; } public String getName() { return name; } /** *Assign a name to this sequence */ public void setName(String name) { this.name = name; } public Annotation getAnnotation() { if(annotation == null) annotation = new SimpleAnnotation(); return annotation; } public int countFeatures() { if(featureHolderAllocated()) return getFeatureHolder().countFeatures(); return 0; } public Iterator features() { if(featureHolderAllocated()) return getFeatureHolder().features(); return Collections.EMPTY_LIST.iterator(); } public FeatureHolder filter(FeatureFilter filter) { return getFeatureHolder().filter(filter); } public FeatureHolder filter(FeatureFilter ff, boolean recurse) { if(featureHolderAllocated()) { return getFeatureHolder().filter(ff, recurse); } return FeatureHolder.EMPTY_FEATURE_HOLDER; } public boolean containsFeature(Feature f) { if(featureHolderAllocated()) { return getFeatureHolder().containsFeature(f); } else { return false; } } public Feature realizeFeature(FeatureHolder parent, Feature.Template template) throws BioException { return featureRealizer.realizeFeature(this, parent, template); } public Feature createFeature(Feature.Template template) throws BioException, ChangeVetoException { Feature f = realizeFeature(this, template); SimpleFeatureHolder fh = this.getFeatureHolder(); fh.addFeature(f); return f; } public FeatureFilter getSchema() { return getFeatureHolder().getSchema(); } /** * Create a new feature in any FeatureHolder associated * with this sequence. * * @deprecated Please use new 1-arg createFeature instead. */ public Feature createFeature(FeatureHolder fh, Feature.Template template) throws BioException, ChangeVetoException { return fh.createFeature(template); } /** * Remove a feature attached to this sequence. */ public void removeFeature(Feature f) throws ChangeVetoException, BioException { getFeatureHolder().removeFeature(f); } public void edit(Edit edit) throws ChangeVetoException { throw new ChangeVetoException("Can't edit the underlying SymbolList"); } public String toString() { return super.toString() + " name: " + getName(); } /** * Create a SimpleSequence with the symbols and alphabet of sym, and the * sequence properties listed. * * @param sym the SymbolList to wrap as a sequence * @param urn the URN * @param name the name - should be unique if practical * @param annotation the annotation object to use or null */ public SimpleSequence(SymbolList sym, String urn, String name, Annotation annotation) { symList = sym; setURN(urn); setName(name); this.annotation = annotation; this.featureRealizer = FeatureImpl.DEFAULT; } /** * Create a SimpleSequence using a specified FeatureRealizer. * * @param sym the SymbolList to wrap as a sequence * @param urn the URN * @param name the name - should be unique if practical * @param annotation the annotation object to use or null * @param realizer the FeatureRealizer implemetation to use when adding features */ public SimpleSequence(SymbolList sym, String urn, String name, Annotation annotation, FeatureRealizer realizer) { symList = sym; setURN(urn); setName(name); this.annotation = annotation; this.featureRealizer = realizer; } // // Changeable stuff // private transient ChangeListener featureForwarder; protected ChangeSupport getChangeSupport(ChangeType ct) { ChangeSupport changeSupport = super.getChangeSupport(ct); if (featureForwarder == null && featureHolder != null) { featureForwarder = new FeatureForwarder(); featureHolder.addChangeListener(featureForwarder, ChangeType.UNKNOWN); } return changeSupport; } private class FeatureForwarder implements ChangeListener { public void preChange(ChangeEvent cev) throws ChangeVetoException { getChangeSupport(cev.getType()).firePreChangeEvent(cev); } public void postChange(ChangeEvent cev) { getChangeSupport(cev.getType()).firePostChangeEvent(cev); } } }