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.alignment;
023
024import java.util.Iterator;
025import java.util.List;
026import java.util.NoSuchElementException;
027import java.util.Set;
028
029import org.biojava.bio.symbol.Location;
030import org.biojava.bio.symbol.Symbol;
031import org.biojava.bio.symbol.SymbolList;
032import org.biojava.utils.ChangeType;
033
034/**
035 * An alignment containing multiple <span class="type">SymbolList</span>s.
036 * <p>
037 * The alignment can be thought of as a rectangular array of <span
038 * class="type">Symbol</span>s. Each row is indexed by a label and each column
039 * is indexed by offset (counting from 1).
040 * <p>
041 * Alternatively, it can be thought of as a <span class="type">SymbolList</span>
042 * where each <span class="type">Symbol</span> is a list of <span
043 * class="type">Symbol</span>s in that column.
044 * <p>
045 * To create gapped alignments, use <span class="type">SymbolList</span>s with
046 * gaps. The most flexible way to do this will be to leverage <span
047 * class="type">GappedSymbolList</span> objects.
048 * 
049 * @author Matthew Pocock
050 * @author Nimesh Singh
051 * @since 1.1
052 */
053public interface Alignment extends SymbolList {
054        /**
055         * Signals that SymbolLists will be added to or removed from an alignment.
056         * The ChangeEvent will record Object[] { label, symbolList } in previous if
057         * it is being removed, in current if it is being added and in both if the
058         * SymbolList for a given name is swapped.
059         */
060        public static final ChangeType CONTENT = new ChangeType(
061                        "The sequences contained in this alignment are being changed",
062                        Alignment.class.getSimpleName(), "CONTENT");
063
064        /**
065         * <p>
066         * The list of SymbolLists in the alignment.
067         * </p>
068         * 
069         * <p>
070         * The index in the list is the same as the index in the alignment. Each
071         * SymbolList object will only be in the alignment once. However, a single
072         * underlying SymbolList may have more than one view within an alignment,
073         * each represented by a different GappedSymbolList.
074         * </p>
075         * 
076         * @return the List of all SymbolLists in the alignment
077         */
078        List<String> getLabels();
079
080        /**
081         * Retrieve a symbol by label and column.
082         * 
083         * @param label
084         *            the SymbolList to retrieve from
085         * @param column
086         *            the index of the column to retrieve
087         * @return the symbol in the symbol list associated with the label at the
088         *         given column
089         * @throws NoSuchElementException
090         *             if there is no row for 'label'
091         */
092        Symbol symbolAt(String label, int column) throws NoSuchElementException;
093
094        /**
095         * Retrieve a single row of the alignment by label.
096         * 
097         * @param label
098         *            the object from which to retrieve the symbol list
099         * @return a SymbolList that contains each token in a row of the alignment
100         * @throws NoSuchElementException
101         *             if there is no row for 'label'
102         */
103        SymbolList symbolListForLabel(String label) throws NoSuchElementException;
104
105        /**
106         * <p>
107         * Make a view onto this alignment.
108         * </p>
109         * 
110         * <p>
111         * If labels is null, then each label will be kept. Otherwise, only those in
112         * labels will be kept. If loc is null, then the entire length of the
113         * alignment will be kept. If loc is not null, then only the columns within
114         * the location will be kept.
115         * </p>
116         * 
117         * @param labels
118         *            the Set of sequences to include by label
119         * @param loc
120         *            the Location to include
121         * @return a sub Alignment
122         * @throws NoSuchElementException
123         *             if labels contains any item that is not a label
124         */
125        Alignment subAlignment(Set<String> labels, Location loc)
126                        throws NoSuchElementException;
127
128        /**
129         * Creates an Iterator over the SymbolLists in the alignment. This should be
130         * similar to iterating over the labels and then fetching each SymbolList,
131         * but the order is not guaranteed to be the same.
132         * 
133         * @return an Iterator
134         */
135        Iterator<SymbolList> symbolListIterator();
136
137        /**
138         * Iterator implementation looping over symbol lists in an alignment using
139         * the labels. This is intended for Alignment implementors.
140         * 
141         * @author Matthew Pocock
142         */
143        public static class SymbolListIterator implements Iterator<SymbolList> {
144                private final Iterator<String> labIt;
145                private final Alignment ali;
146
147                /**
148                 * Creates a SymbolListIterator for a given alignment object.
149                 * 
150                 * @param ali
151                 */
152                public SymbolListIterator(Alignment ali) {
153                        this.ali = ali;
154                        this.labIt = ali.getLabels().iterator();
155                }
156
157                /*
158                 * (non-Javadoc)
159                 * 
160                 * @see java.util.Iterator#hasNext()
161                 */
162                public boolean hasNext() {
163                        return labIt.hasNext();
164                }
165
166                /*
167                 * (non-Javadoc)
168                 * 
169                 * @see java.util.Iterator#next()
170                 */
171                public SymbolList next() {
172                        return ali.symbolListForLabel(labIt.next());
173                }
174
175                /*
176                 * (non-Javadoc)
177                 * 
178                 * @see java.util.Iterator#remove()
179                 */
180                public void remove() {
181                        labIt.remove();
182                }
183        }
184}