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
024import java.util.Iterator;
025
026/**
027 * A set of integers, often used to represent positions on biological sequences.
028 *
029 * <p>
030 * The location will contain some indices between getMin and getMax inclusive.
031 * It is not required to contain all indices within this range. It is meant
032 * to contain the indices returned by the getMin or getMax. In the event that
033 * an operation would produce an
034 * invalid or nonsensical range, <code>Location.empty</code> should be returned.
035 * </p>
036 *
037 * <p>
038 * Location objects are <strong>always</strong> immutable.
039 * </p>
040 *
041 * <h2>Working with locations</h2>
042 *
043 * <p>
044 * Locations can be constructed in a number of ways:
045 * </p>
046 *
047 * <pre>
048 * Location l1 = LocationTools.makeLocation(10, 20);  // Makes a RangeLocation
049 * Location l2 = LocationTools.makeLocation(25, 25);  // Makes a PointLocation
050 * Location l3 = LocationTools.union(l1, l2); // Construct a non-contiguous
051 *                                            // location containing the
052 *                                            // points from l1 and l2
053 * </pre>
054 *
055 * @author Matthew Pocock
056 * @author Thomas Down
057 */
058
059public interface Location {
060  /**
061   * Create a new instance of Location with all of the same decorators as this
062   * instance but with the data stored in <code>loc</code>.
063   * <p>
064   * The default behavior is to return <loc>loc</loc> unchanged. If the class is
065   * a location decorator then it should instantiate an instance of the same
066   * type that decorates <code>loc</code>.
067   *
068   * @param loc  the Location to use as template
069   * @return a Location instance based on loc with the same decorators as the
070   *         current instance
071   */
072  Location newInstance(Location loc);
073
074  /**
075   * Checks the decorator chain for an instance of <class>decoratorClass</class>
076   * and return it if found.
077   * <p>
078   * The default behavior is to return null. If the current object is a
079   * decorator and is an instance of <class>decoratorClass</class> it should
080   * return itself. Otherwise, the decorator should chain this method onto the
081   * instance it wraps.
082   *
083   * @param decoratorClass  the Class to check
084   * @return a Location if an instance of this class is present in the decorator
085   *         chain and null otherwise.
086   */
087  Location getDecorator(Class decoratorClass);
088  /**
089   * The minimum position contained.
090   * <p>
091   * <b>WARNING:</b> The location will <b>not</b> contain every point between <code>getMin()</code>
092   * and <code>getMax()</code> if <code>isContiguous()</code> is false. If <code>isContiguous()</code>
093   * does return false you should use the <code>Iterator</code> returned by <code>blockIterator()</code>
094   * to iterate over the minimum set of contiguous blocks that make up this <code>Location</code>
095   *
096   * @return    the minimum position contained
097   */
098  int getMin();
099  /**
100   * The maximum position contained.
101   * <p>
102   * <b>WARNING:</b> The location will <b>not</b> contain every point between <code>getMin()</code>
103   * and <code>getMax()</code> if <code>isContiguous()</code> is false. If <code>isContiguous()</code>
104   * does return false you should use the <code>Iterator</code> returned by <code>blockIterator()</code>
105   * to iterate over the minimum set of contiguous blocks that make up this <code>Location</code>
106   *
107   * @return    the maximum position contained
108   */
109  int getMax();
110
111  /**
112   * Checks if these two locations overlap, using this location's
113   * concept of overlapping.
114   * <p>
115   * Abstractly, two locations overlap if they both contain any point.
116   *
117   * @param l   the Location to check
118   * @return    true if they overlap, otherwise false
119   *
120   */
121  boolean overlaps(Location l);
122  /**
123   * Checks if this location contains the other.
124   * <p>
125   * Abstractly, a location contains another if every point in the
126   * other location is contained within this one.
127   *
128   * @param l   the Location to check
129   * @return    true if this contains l, otherwise false
130   *
131   */
132  boolean contains(Location l);
133  /**
134   * Checks if this location contains a point.
135   *
136   * @param p   the point to check
137   * @return    true if this contains p, otherwise false
138   */
139  boolean contains(int p);
140
141  /**
142   * Checks if this location is equivalent to the other.
143   * <p>
144   * Abstractly, a location is equal to another if for every point in one
145   * it is also in the other. This is equivalent to
146   * a.contains(b) && b.contains(a). You should call LocationTools.areEqual
147   * after casting l to Location.
148   *
149   * @param l   the Object to check
150   * @return    true if this equals l, otherwise false
151   */
152  boolean equals(Object l);
153
154  /**
155   * Returns a Location that contains all points common to both ranges.
156   *
157   * @param l   the Location to intersect with
158   * @return    a Location containing all points common to both, or
159   *              the empty range if there are no such points
160   *
161   */
162  Location intersection(Location l);
163  /**
164   * Return a Location containing all points in either ranges.
165   *
166   * @param l   the Location to union with
167   * @return    a Location representing the union
168   *
169   */
170  Location union(Location l);
171
172  /**
173   * Return the symbols in a sequence that fall within this range.
174   *
175   * @param seq the SymbolList to process
176   * @return    the SymbolList containing the symbols in seq in this range
177   *
178   */
179  SymbolList symbols(SymbolList seq);
180
181  /**
182   * Create a location that is a translation of this location.
183   *
184   * @param dist  the distance to translate (to the right)
185   */
186  Location translate(int dist);
187
188  /**
189   * Determine if a Location is contiguous.
190   *
191   * @return <code>true</code> if and only if this Location
192   *         contains every point from <code>min</code> to
193   *         <code>max</code> inclusive.
194   */
195  boolean isContiguous();
196
197  /**
198   * Return an Iterator over the set of maximal contiguous sub-locations.
199   * <p>
200   * Given any location, it can be considered to contain zero or more
201   * maximal contiguous blocks of width 1 or greater. The empty location is
202   * composed from nothing. A contiguous location is composed from itself.
203   * A non-contiguous location is composed from contiguous blocks seperated by
204   * gaps.
205   * <p>
206   * This method should return an Iterator over these maximally contiguous blocks
207   * starting with the left-most block, and finishing at the right-most block.
208   *
209   * @return an Iterator over Location objects that are the maximally contiguous
210   *         set of locations contained within this location
211   */
212  Iterator<Location> blockIterator();
213
214  /**
215   * The <code>Location</code> which contains no points.
216   *
217   * <p>
218   * This object contains nothing. Its minimum value is Integer.MAX_VALUE.
219   * Its maximum value is Integer.MIN_VALUE. It overlaps nothing. It is
220   * equal to nothing. Intersection results in the empty range. Union
221   * results in the argument range. Symbols returns an empty array.
222   * <p>
223   * Every day, in every way, empty becomes more and more boring.
224   */
225  public static final Location empty = new EmptyLocation();
226  
227  /**
228   * The <code>Location</code> which contains all points.
229   *
230   * <p>
231   * This object contains every point. It's minimum value is Integer.MIN_VALUE,
232   * and it's maximum value is Integer.MAX_VALUE. It overlaps and contains
233   * everything.
234   * </p>
235   */
236  public static final Location full = new RangeLocation(Integer.MIN_VALUE, Integer.MAX_VALUE);
237
238  /**
239   * Comparator which orders Locations naturally.  Locations
240   * are sorted primarily on the basis of their <code>getMin()</code>
241   * value.  In cases where that is equal, they are secondarily sorted
242   * by <code>getMax()</code> value.
243   */
244
245  static final LocationComparator naturalOrder = new LocationComparator();
246}
247