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