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.symbol;
023
024/**
025 * This extends SymbolList with API for manipulating, inserting and deleting
026 * gaps.
027 * <p>
028 * You could make a SymbolList that contains gaps directly. However, this leaves
029 * you with a nasty problem if you wish to support gap-edit operations. Also,
030 * the original SymbolList must either be coppied or lost.
031 * <p>
032 * GappedSymbolList solves these problems. It will maintain a data-structure
033 * that places gaps. You can add and remove the gaps by using the public API.
034 * <p>
035 * For gap-insert operations, the insert index is the position that will become
036 * a gap. The symbol currently there will move to a higher index. To insert
037 * leading gaps, add gaps at index 1. To insert trailing gaps, add gaps at index
038 * length+1.
039 * 
040 * @author Matthew Pocock
041 * @since 1.3
042 */
043public interface GappedSymbolList extends SymbolList {
044        /**
045         * Return the underlying (ungapped) SymbolList.
046         * 
047         * @since 1.4
048         */
049        public SymbolList getSourceSymbolList();
050
051        /**
052         * Coordinate conversion from view to source.
053         * <p>
054         * If the index can be projected onto the source, the index it projects onto
055         * is returned. If it falls within a gap, then the index of the first symbol
056         * after the run of gaps is negated and returned. If the index is after the
057         * last block of symbols (and therefore in the trailing list of gaps), then
058         * it returns -(length + 1).
059         * 
060         * @param indx
061         *            the index to project
062         * @return the position of indx projected from view to source
063         * @throws IndexOutOfBoundsException
064         *             if indx is not a valid view index
065         */
066        public int viewToSource(int indx) throws IndexOutOfBoundsException;
067
068        /**
069         * Coordinate conversion from source to view.
070         * 
071         * @param indx
072         *            the index to project
073         * @return the position of indx projected from source to view
074         * @throws IndexOutOfBoundsException
075         *             if indx is not a valid source index
076         */
077        public int sourceToView(int indx) throws IndexOutOfBoundsException;
078
079        /**
080         * Add a single gap at pos within the view coordintates.
081         * <p>
082         * this.symbolAt(pos) will then return gap. Adding a gap at 1 will prepend
083         * gaps. Adding a gap at (length+1) will append a gap.
084         * 
085         * @param pos
086         *            the position to add a gap before
087         * @throws IndexOutOfBoundsException
088         *             if pos is not within 1->length+1
089         */
090        public void addGapInView(int pos) throws IndexOutOfBoundsException;
091
092        /**
093         * Add length gaps at pos within the view coordinates.
094         * <p>
095         * this.symbolAt(i) will then return gap for i = (pos .. pos+count-1).
096         * Adding gaps at 1 will prepend gaps. Adding gaps at (length+1) will append
097         * gaps.
098         * 
099         * @param pos
100         *            the position to add a gap before
101         * @param length
102         *            the number of gaps to insert
103         * @throws IndexOutOfBoundsException
104         *             if pos is not within 1->length+1
105         */
106        public void addGapsInView(int pos, int length)
107                        throws IndexOutOfBoundsException;
108
109        /**
110         * Add a gap at pos within the source coordinates.
111         * 
112         * @param pos
113         *            where to add the gap
114         * @throws IndexOutOfBoundsException
115         *             if pos is not within 1->source.length()
116         */
117        public void addGapInSource(int pos) throws IndexOutOfBoundsException;
118
119        /**
120         * Add length gaps at pos within the source coordinates.
121         * 
122         * @param pos
123         *            where to add the gap
124         * @param length
125         *            how many gaps to add
126         * @throws IndexOutOfBoundsException
127         *             if pos is not within 1->source.length()
128         */
129        public void addGapsInSource(int pos, int length)
130                        throws IndexOutOfBoundsException;
131
132        /**
133         * Remove a single gap at position pos in this GappedSymbolList.
134         * 
135         * @param pos
136         *            where to remove the gap
137         * @throws IndexOutOfBoundsException
138         *             if pos is not within 1..length
139         * @throws IllegalSymbolException
140         *             if the symbol at pos is not a gap
141         */
142        public void removeGap(int pos) throws IndexOutOfBoundsException,
143                        IllegalSymbolException;
144
145        /**
146         * Remove some gaps at position pos in this GappedSymbolList.
147         * 
148         * @param pos
149         *            where to remove the gaps
150         * @param length
151         *            how many to remove
152         * @throws IndexOutOfBoundsException
153         *             if pos is not within 1..length() or if some of the Symbols
154         *             within pos->(pos+length-1) are not gap Symbols
155         * @throws IllegalSymbolException
156         *             if the symbol at pos is not a gap
157         */
158        public void removeGaps(int pos, int length)
159                        throws IndexOutOfBoundsException, IllegalSymbolException;
160
161        /**
162         * Return the index of the first Symbol that is not a Gap character.
163         * <p>
164         * All symbols before firstNonGap are leading gaps. firstNonGap is
165         * effectively the index in the view of symbol 1 in the original sequence.
166         * 
167         * @return the index of the first character not to be a gap
168         */
169        public int firstNonGap();
170
171        /**
172         * Return the index of the last Symbol that is not a Gap character.
173         * <p>
174         * All symbols after lastNonGap untill length are trailing gaps. lastNonGap
175         * is effectively the index in the view of symbol length in the original
176         * sequence.
177         * 
178         * @return the index of the last character not to be a gap
179         */
180        public int lastNonGap();
181
182        /**
183         * Get a Location that contains exactly those positions that are not gaps.
184         * 
185         * <p>
186         * This will be a Location that contains every symbol in the underlying
187         * ungapped sequence. Every symbol not in the Location is not from the
188         * underlying sequence and is a gap.
189         * </p>
190         * 
191         * @return a new Location that contains all non-gap symbols
192         */
193        public Location getUngappedLocation();
194
195}