001 /* 002 * Copyright 2007, 2012 Stephen Fisher and Junhyong Kim, University of 003 * Pennsylvania. 004 * 005 * This file is part of Glo-DB. 006 * 007 * Glo-DB is free software: you can redistribute it and/or modify it 008 * under the terms of the GNU General Public License as published by 009 * the Free Software Foundation, either version 3 of the License, or 010 * (at your option) any later version. 011 * 012 * Glo-DB is distributed in the hope that it will be useful, but 013 * WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with Glo-DB. If not, see <http://www.gnu.org/licenses/>. 019 * 020 * @(#)ExactFeature.java 021 */ 022 023 package edu.upenn.gloDB; 024 025 /** 026 * These objects store exact positions bounding a Feature. For point 027 * Features just set start and stop equal. At some point it might be 028 * advantageous to create a PointFeature class which would only have 029 * one position. 030 * 031 * @author Stephen Fisher 032 * @version $Id: ExactFeature.java,v 1.1.2.9 2005/01/07 19:56:59 fisher Exp $ 033 */ 034 035 public class ExactFeature extends AbstractFeature { 036 037 /** The initial position defining this Feature. */ 038 private int start; 039 040 /** The last position defining this Feature. */ 041 private int stop; 042 043 044 /** 045 * Create a new ExactFeature object and add it to the set of 046 * Feature objects. 047 */ 048 public ExactFeature(int start, int stop, Sequence source) { 049 this(start, stop, source, true); 050 } 051 052 /** 053 * Create a new ExactFeature object and add the newly created 054 * ExactFeature object to the set of Feature objects if addToPool 055 * is true. 056 * @XXX This should probably be 'protected' instead of 'public' 057 * because all ExactFeatures should really be added to 058 * featurePool. 059 */ 060 public ExactFeature(int start, int stop, Sequence source, boolean addToPool) { 061 super(source); 062 063 // start/stop aren't allowed to change, so this is the only 064 // place they should be set. 065 this.start = start; 066 this.stop = stop; 067 068 // add self to set of all Features 069 if (addToPool) ObjectHandles.addFeature(this); 070 } 071 072 073 //-------------------------------------------------------------------------- 074 // Setters and Getters 075 076 /** Returns the start position. */ 077 public int getStart() { return start; } 078 079 /** Returns the stop position. */ 080 public int getStop() { return stop; } 081 082 //-------------------------------------------------------------------------- 083 // Miscellaneous Methods 084 085 /** 086 * Returns the Sequence data from start to stop. 087 */ 088 public String getData() { return getSource().getDataBounded(start, stop); } 089 090 /** 091 * Returns the Sequence data from start to stop, with "\n" 092 * inserted every Sequence.FORMAT_WIDTH characters (usually 50 to 093 * 80 chars). 094 */ 095 public String getDataFormatted() { 096 return getSource().getDataBoundedFormatted(start, stop); 097 } 098 099 /** 100 * Returns the number of positions contained in the Feature ((stop 101 * - start) + 1). 102 */ 103 public int length() { return ((stop - start) + 1); } 104 105 /** 106 * Returns the initial position of the Feature. 107 * @XXX This will return the same value as getStart(). 108 */ 109 public int getMin() { return start; } 110 111 /** 112 * Returns the maximum position of the Feature. 113 * @XXX This will return the same value as getStop(). 114 */ 115 public int getMax() { return stop; } 116 117 /** 118 * Inverts the positions, returning a new Feature object. For 119 * example, if the Feature had a start position of 10 and a stop 120 * position of 20 on a contig that was 100 positions long, then 121 * flipping the Feature would result in a new Feature object with 122 * a start position of 80 and a stop position of 90. 123 * @XXX Not yet implemented. 124 */ 125 public Feature flip() { return null; } 126 127 /** 128 * Returns '-1' if this Feature exists after the integer 'pos', 129 * returns '0' if 'pos' is contained in this Feature, and '1' if 130 * 'pos' occurs after this Feature. 131 * @XXX This assumes 'pos' is positive and within this Feature's 132 * Sequence boundaries. 133 */ 134 public int contains(int pos) { 135 return FeatureUtils.contains(this, pos); 136 } 137 138 /** 139 * Returns 'true' if the Feature 'feature' exists within this 140 * Feature. 141 */ 142 public boolean contains(Feature feature) { 143 return FeatureUtils.contains(this, feature); 144 } 145 146 /** 147 * Returns 'true' if the Feature 'feature' has a position that 148 * overlaps this Feature. 149 */ 150 public boolean overlaps(Feature feature) { 151 return FeatureUtils.overlaps(this, feature); 152 } 153 154 /** 155 * Returns the overlapping region between the two Features. If no 156 * overlap, then null is returned. 157 */ 158 public Feature overlap(Feature feature) { 159 return FeatureUtils.overlap(this, feature); 160 } 161 162 /** 163 * Compares this object with the specified object for order. 164 * Returns a negative integer, zero, or a positive integer as this 165 * object is less than, equal to, or greater than the specified 166 * object. If can't cast argument as an Feature, then throws a 167 * java.lang.ClassCastException. If different sources, then sorts 168 * on the source ID. 169 */ 170 public int compareTo(Object o) throws ClassCastException { 171 // convert object to Feature 172 Feature featureTo; 173 try { 174 featureTo = (Feature) o; 175 } catch (ClassCastException e) { 176 throw new ClassCastException("ExactFeature.compareTo() requires an argument of type Feature."); 177 } 178 return FeatureUtils.compareFeatures(this, featureTo); 179 } 180 181 /** 182 * This will return true if the features are equal and the 183 * sources are the same. If can't cast argument as an 184 * ExactFeature, then throws a java.lang.ClassCastException. 185 */ 186 public boolean equals(Object o) throws ClassCastException { 187 // make sure we got an 'ExactFeature' object 188 if (GloDBUtils.getClassName(o) != "ExactFeature") return false; 189 190 // convert object to Feature 191 ExactFeature featureTo; 192 try { 193 featureTo = (ExactFeature) o; 194 } catch (ClassCastException e) { 195 throw new ClassCastException("ExactFeature.equals() requires an argument of type ExactFeature."); 196 } 197 198 // check of same source 199 if (source != featureTo.source) return false; 200 201 // check if start and stop are equal 202 if ((start == featureTo.getStart()) && (stop == featureTo.getStop())) { 203 return true; 204 } else { 205 return false; 206 } 207 } 208 209 /** Only basic Feature information. */ 210 public String toString() { 211 String out = "Exact Feature (" + source + "): "; 212 out += "(" + Integer.toString(start) + ".." + Integer.toString(stop) + ") \n"; 213 return out; 214 } 215 216 /** Only returns start/stop position information. */ 217 public String toStringMin() { 218 return "(" + Integer.toString(start) + ".." + Integer.toString(stop) + ")"; 219 } 220 221 /** Returns all Feature information. */ 222 public String toStringFull() { 223 String out = "Exact Feature:\n"; 224 // String out = "Exact Feature (" + source + "): "; 225 // out += "(" + Integer.toString(start) + ".." + Integer.toString(stop) + ") \n"; 226 227 out += "Start: " + Integer.toString(start) + "\n"; 228 out += "Stop: " + Integer.toString(stop) + "\n"; 229 230 out += super.toString(); // get attributes and source info 231 232 return out; 233 } 234 235 } // ExactFeature.java