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.homol;
023
024import java.util.ArrayList;
025import java.util.Collections;
026import java.util.Iterator;
027import java.util.List;
028import java.util.NoSuchElementException;
029import java.util.Set;
030
031import org.biojava.bio.alignment.Alignment;
032import org.biojava.bio.seq.StrandedFeature;
033import org.biojava.bio.symbol.Alphabet;
034import org.biojava.bio.symbol.Edit;
035import org.biojava.bio.symbol.IllegalAlphabetException;
036import org.biojava.bio.symbol.Location;
037import org.biojava.bio.symbol.Symbol;
038import org.biojava.bio.symbol.SymbolList;
039import org.biojava.utils.ChangeType;
040import org.biojava.utils.ChangeVetoException;
041import org.biojava.utils.Unchangeable;
042
043/**
044 * <p><code>SimilarityPairFeature</code> describes a pairwise
045 * similarity between two nucleotide sequences (as it extends
046 * <code>StrandedFeature</code>). It is analagous to, and based on,
047 * the BioPerl Bio::SeqFeature::SimilarityPair.</p>
048 *
049 * <p>It is different from <code>HomologyFeature</code> in that it
050 * expresses a relationship between only two sequence regions (rather
051 * than >= 2), with one clearly defined as the query sequence and the
052 * other as the subject (database hit). These are identified by
053 * constant labels in the
054 * <code>Alignment</code>. <code>HomologyFeature</code> identifies the
055 * related sequence regions by means of an <code>Homology</code>
056 * instance which contains an <code>Alignment</code> which uses the
057 * <code>HomologyFeature</code>s themselves as labels.</p>
058 *
059 * <p>In cases where there is no alignment available, for example when
060 * MSPCrunch output or GFF have been used, the
061 * <code>EmptyPairwiseAlignment</code> in the EMPTY_PAIRWISE field may
062 * be used. This may also be useful if an implementation elides the
063 * alignment data for some reason.</p>
064 *
065 * @author Keith James
066 * @since 1.2
067 */
068public interface SimilarityPairFeature extends StrandedFeature
069{
070    /**
071     * The sibling of this feature has altered.
072     */
073    public static final ChangeType SIBLING =
074        new ChangeType("Sibling has altered", SimilarityPairFeature.class, "SIBLING");
075
076    /**
077     * Constant <code>QUERY_LABEL</code> is the alignment label used
078     * for all query sequences.
079     */
080    public static final String QUERY_LABEL = "query";
081
082    /**
083     * Constant <code>SUBJECT_LABEL</code> is the alignment label used
084     * for all subject sequences.
085     */
086    public static final String SUBJECT_LABEL = "subject";
087
088    /**
089     * Constant <code>EMPTY_PAIRWISE</code> is an empty alignment for
090     * situations where there is no available alignment data or the
091     * implementation does not want to create one.
092     */
093    public static final Alignment EMPTY_PAIRWISE = new EmptyPairwiseAlignment();
094
095    /**
096     * <code>getSibling</code> returns the sibling
097     * <code>Feature</code>, query for subject and vice versa.
098     *
099     * @return a <code>Feature</code>.
100     */
101    public SimilarityPairFeature getSibling();
102
103    /**
104     * <code>setSibling</code> sets the sibling feature of the
105     * pair. This is used to set the reciprocal
106     * <code>SimilarityPairFeature</code> as both cannot be set using
107     * the <code>Template</code>.
108     */
109    public void setSibling(SimilarityPairFeature sibling)
110        throws ChangeVetoException;
111
112    /**
113     * <code>getAlignment</code> returns the <code>Alignment</code> of
114     * two similar features.
115     *
116     * @return an <code>Alignment</code> value.
117     */
118    public Alignment getAlignment();
119
120    /**
121     * <code>getScore</code> returns the alignment score.
122     *
123     * @return a <code>double</code>.
124     */
125    public double getScore();
126
127    /**
128     * <code>Template</code> for construction of
129     * <code>SimilarityPairFeature</code>s.
130     */
131    public static class Template extends StrandedFeature.Template
132    {
133        /**
134         * <code>sibling</code> <code>SimilarityPairFeature</code>
135         * field. May be null if the reciprocal
136         * <code>SimilarityPairFeature</code> has not yet been
137         * created.
138         */
139        public SimilarityPairFeature sibling;
140
141        /**
142         * <code>alignment</code> <code>Alignment</code> field.
143         */
144        public Alignment alignment;
145
146        /**
147         * <code>score</code> of the search which produced the
148         * alignment.
149         */
150        public double score;
151    }
152
153    /**
154     * <code>EmptyPairwiseAlignment</code> empty pairwise alignment
155     * which has labels to empty symbol lists.
156     */
157    static final class EmptyPairwiseAlignment extends Unchangeable
158        implements Alignment
159    {
160        private List<String> labels = new ArrayList<String>(2);
161
162        EmptyPairwiseAlignment()
163        {
164            labels = new ArrayList<String>(2);
165            labels.add(QUERY_LABEL);
166            labels.add(SUBJECT_LABEL);
167        }
168
169        public List<String> getLabels()
170        {
171            return labels;
172        }
173
174        public Symbol symbolAt(String label, int index)
175            throws NoSuchElementException
176        {
177            throw new NoSuchElementException("Attempted to retrieve symbol from empty list at "
178                                             + label
179                                             + ":"
180                                             + index);
181        }
182
183        public SymbolList symbolListForLabel(String label)
184            throws NoSuchElementException
185        {
186            return SymbolList.EMPTY_LIST;
187        }
188
189        public Alignment subAlignment(Set<String> labels, Location loc)
190            throws NoSuchElementException
191        {
192            throw new NoSuchElementException("Attempted to retrieve sub-alignment from empty list at "
193                                             + labels
194                                             + ":"
195                                             + loc);
196        }
197
198        public int length()
199        {
200            return 0;
201        }
202
203        public Iterator iterator()
204        {
205            return Collections.EMPTY_LIST.iterator();
206        }
207
208        public SymbolList subList(int index1, int index2)
209            throws IndexOutOfBoundsException
210        {
211            Collections.EMPTY_LIST.subList(index1 - 1, index2);
212            return SymbolList.EMPTY_LIST;
213        }
214
215        public Symbol symbolAt(int index) throws IndexOutOfBoundsException
216        {
217            throw new IndexOutOfBoundsException("Attempted to retrieve symbol from empty list at "
218                                                + index);
219        }
220
221        public Alphabet getAlphabet()
222        {
223            return Alphabet.EMPTY_ALPHABET;
224        }
225
226        public List toList()
227        {
228            return Collections.EMPTY_LIST;
229        }
230
231        public String seqString()
232        {
233            return "";
234        }
235
236        public String subStr(int index1, int index2)
237            throws IndexOutOfBoundsException
238        {
239            throw new IndexOutOfBoundsException("You can not retrieve part of an empty symbol list");
240        }
241
242        public void edit(Edit edit)
243            throws IndexOutOfBoundsException,IllegalAlphabetException,
244                   ChangeVetoException
245        {
246            throw new ChangeVetoException("You can't edit the empty symbol list");
247        }
248      
249        public Iterator<SymbolList> symbolListIterator()
250        {
251            return new Alignment.SymbolListIterator(this);
252        }
253    }
254}