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