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.seq;
022 
023import java.io.NotSerializableException;
024import java.io.ObjectStreamException;
025import java.io.Serializable;
026
027import org.biojava.bio.symbol.SymbolList;
028import org.biojava.utils.ChangeType;
029import org.biojava.utils.ChangeVetoException;
030import org.biojava.utils.StaticMemberPlaceHolder;
031
032/**
033 * Adds the concept of 'strand' to features.
034 * <p>
035 * Strandedness only applies to some types of sequence, such as DNA. Any
036 * implementation should blow chunks to avoid being added to a sequence for
037 * which strand is a foreign concept.
038 *
039 * Strand is intrinsicly part of all {@link org.biojavax.bio.seq.RichFeature RichFeatures}
040 * We strongly recommend using this interface.
041 *
042 * @author Matthew Pocock
043 *@see org.biojavax.bio.seq.RichFeature
044 */
045public interface StrandedFeature extends Feature {
046
047  /**
048   * The strand of this feature is being altered.
049   */
050  public static final ChangeType STRAND =
051      new ChangeType("Strand has altered", StrandedFeature.class, "STRAND");
052
053  /**
054   * Retrieve the strand that this feature lies upon.
055   * <p>
056   * This will be one of StrandedFeature.POSITIVE or NEGATIVE.
057   *
058   * @return one of the Strand constants
059   */
060  Strand getStrand();
061
062  /**
063   * Set the strand that this feature lies upon.
064   * <p>
065   * This will be one of StrandedFeature.POSITIVE or NEGATIVE.
066   *
067   * @param strand a <code>Strand</code>.
068   *
069   * @exception ChangeVetoException if the strand may not be
070   * changed.
071   */
072  void setStrand(Strand strand) throws ChangeVetoException;
073
074  /**
075   * Return a list of symbols that are contained in this feature.
076   * <p>
077   * The symbols may not be contiguous in the original sequence, but they
078   * will be concatenated together in the resulting SymbolList.
079   * <p>
080   * The order of the Symbols within the resulting symbol list will be 
081   * according to the concept of ordering within the location object.
082   * <p>
083   * If the feature is on the negative strand then the SymbolList will be
084   * reverse-complemented as appropriate.
085   *
086   * @return  a SymbolList containing each symbol of the parent sequence contained
087   *          within this feature in the order they appear in the parent
088   */
089  SymbolList getSymbols();
090  
091  /**
092   * Flag to indicate that a feature is on the positive strand.
093   */
094  static final Strand POSITIVE = new Strand("POSITIVE", +1, '+');
095
096  /**
097   * Flag to indicate that a feature is on the negative strand.
098   */
099  static final Strand NEGATIVE = new Strand("NEGATIVE", -1, '-');
100  
101  /**
102   * Flag to indicate that a feature has an unknown strand.
103   */
104  static final Strand UNKNOWN = new Strand("UNKNOWN", 0, '.');
105  
106    /**
107     * Template class for parameterizing the creation of a new
108     * <code>StrandedFeature</code>.
109     *
110     * @author Matthew Pocock
111     */
112
113  public static class Template extends Feature.Template {
114    public Strand strand;
115  }
116  
117  /**
118   * Class to represent the 'strandedness' of a feature.
119   * <p>
120   * Strandedness may be re-used in other situations, but basically what it means
121   * is whether the feature has directionality, and if it does, does it travel
122   * from its location min to max, or max to min.
123   *
124   * @author Matthew Pocock
125   */
126  public static final class Strand implements Serializable {
127    private final String text;
128    private final int value;
129    private final char token;
130    
131    // Should be private. workaround for known javac 1.2 bug
132    // http://developer.java.sun.com/developer/bugParade/bugs/4262105.html
133    Strand(String text, int value, char token) {
134      this.text = text;
135      this.value = value;
136      this.token = token;
137    }
138    public String toString() {
139      return text;
140    }
141    
142   /**
143    * Returns the integer label for strandedness. That is, "+1", "-1",
144    * or "0" for positive, negative, and unknown strands respectively.
145    */
146    public int getValue() {
147      return value;
148    }
149    
150   /**
151    * Returns the token for strandedness. That is, "+","-","." for
152    * positive, negative and unknown strands respectively.
153    */
154    public char getToken() {
155      return token;
156    }
157
158    /**
159     * Return a strand that represents flipping this onto the opposite strand.
160     */
161    public Strand flip() {
162      if(this == POSITIVE) {
163        return NEGATIVE;
164      } else if(this == NEGATIVE) {
165        return POSITIVE;
166      } else {
167        return this;
168      }
169    }
170
171    private Object writeReplace() throws ObjectStreamException {
172      try {
173        return new StaticMemberPlaceHolder(StrandedFeature.class.getField(text));
174      } catch (NoSuchFieldException nsfe) {
175        throw new NotSerializableException(nsfe.getMessage());
176      }
177    }
178  }
179}