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     * @(#)FuzzyFeature.java
021     */
022    
023    package edu.upenn.gloDB;
024    
025    /**
026     * These objects code Features that don't have definite boundaries.
027     * It's not clear whether it's more advantagous to have separate class
028     * definitions:
029     *   FuzzyFeature - make abstract class
030     *   BetweenFeature - same fields as below
031     *   AfterFeature - no stop -> stop = sequence length; stopExtension = 0
032     *   BeforeFeature - no start -> start = 0; startExtension = 0
033     *
034     * @author  Stephen Fisher
035     * @version $Id: FuzzyFeature.java,v 1.1.2.9 2007/03/01 21:17:32 fisher Exp $
036     */
037    
038    public class FuzzyFeature extends AbstractFeature { 
039             /** The initial position defining this Feature. */
040             private int start;
041    
042             /** The number of the positions defining the start position. */
043             private int startExt;
044    
045             /** The last position defining this Feature. */
046             private int stop;
047    
048             /** The number of the positions defining the stop position. */
049             private int stopExt;
050    
051    
052             /** 
053              * Create a new FuzzyFeature object and add it to the set of
054              * Feature objects.
055              */
056             public FuzzyFeature(int start, int startExt, int stop, int stopExt, Sequence source) { 
057                      this(start, startExt, stop, stopExt, source, true);
058             }
059    
060             /** 
061              * Create a new FuzzyFeature object and add the newly created
062              * FuzzyFeature object to the set of Feature objects if addToPool
063              * is true.
064              * @XXX This should probably be 'protected' instead of 'public'
065              * because all FuzzyFeatures should really be added to
066              * featurePool.
067              */
068             public FuzzyFeature(int start, int startExt, int stop, int stopExt, Sequence source, boolean addToPool) {
069                      super(source);
070    
071                      // these aren't allowed to change, so this is the only place
072                      // they should be set.
073                      this.start = start;
074                      this.startExt = startExt;
075                      this.stop = stop;
076                      this.stopExt = stopExt;
077    
078                      // add self to set of all Features
079                      if (addToPool) ObjectHandles.addFeature(this);
080             }
081    
082    
083        //--------------------------------------------------------------------------
084        // Setters and Getters
085       
086        /** Returns the start position. */
087        public int getStart() { return start; }
088             
089        /** Returns the startExt position. */
090        public int getStartExt() { return startExt; }
091             
092        /** Returns the stop position. */
093        public int getStop() { return stop; }
094             
095        /** Returns the stopExt. */
096        public int getStopExt() { return stopExt; }
097             
098        //--------------------------------------------------------------------------
099        // Miscellaneous Methods
100       
101             /** 
102              * Returns the Sequence data from start to stopExt.  Note that
103              * this includes the fuzzy boundaries.
104              */
105             public String getData() { 
106                      return getSource().getDataBounded(start, stopExt); 
107             }
108    
109             /** 
110              * Returns the Sequence data from start to stopExt, with "\n"
111              * inserted every 80 characters.
112              */
113             public String getDataFormatted() { 
114                      return getSource().getDataBoundedFormatted(start, stopExt); 
115             }
116    
117             /**
118              * Returns the maximum number of positions contained in the
119              * Feature (((stop + stopExt) - start) + 1).
120              */
121             public int length() { return (((stop + stopExt) - start) + 1); }
122    
123             /**
124              * Returns the initial position of the Feature.
125              */
126             public int getMin() { return start; }
127    
128             /**
129              * Returns the maximum position of the Feature.
130              */
131             public int getMax() { return stopExt; }
132    
133             /**
134              * Returns the minimum number of positions contained in the
135              * Feature ((stop - start) + 1).
136              */
137             public int minLength() { return ((stop - start) + 1); }
138    
139             /**
140              * This is the same as {@link #length() length()}.
141              */
142             public int maxLength() { return length(); }
143    
144             /**
145              * Inverts the positions, returning a new Feature object.  For
146              * example, if the Feature had a start position of 10 and a stop
147              * position of 20 on a contig that was 100 positions long, then
148              * flipping the Feature would result in a new Feature object with
149              * a start position of 80 and a stop position of 90.
150              * @XXX Not yet implemented.
151              */
152             public Feature flip() { return null; }
153    
154             /**
155              * Returns '-1' if this Feature exists after the integer 'pos',
156              * returns '0' if 'pos' is contained in this Feature, and '1' if
157              * 'pos' occurs after this Feature.
158              * @XXX This assumes 'pos' is positive within this Feature's
159              * Sequence boundaries.
160              */
161             public int contains(int pos) {
162                      return FeatureUtils.contains(this, pos);
163             }
164    
165             /**
166              * Returns 'true' if the Feature 'feature' is contained in this
167              * Feature.
168              */
169             public boolean contains(Feature feature) { 
170                      return FeatureUtils.contains(this, feature);
171             }
172    
173             /**
174              * Returns 'true' if the feature 'featCk' has positions that
175              * overlap positions in this feature.
176              */
177             public boolean overlaps(Feature feature) {
178                      return FeatureUtils.overlaps(this, feature); 
179             }
180    
181             /**
182              * Returns the overlapping region between the two Features.  If no
183              * overlap, then null is returned.
184              */
185             public Feature overlap(Feature feature) { 
186                      return FeatureUtils.overlap(this, feature);
187             }
188    
189             /**
190              * Compares this object with the specified object for order.
191              * Returns a negative integer, zero, or a positive integer as this
192              * object is less than, equal to, or greater than the specified
193              * object.  If can't cast argument as an Feature, then throws a
194              * java.lang.ClassCastException.  If different sources, then sorts
195              * on the source ID.
196              *
197              */
198             public int compareTo(Object o) throws ClassCastException {
199                      // convert object to Feature
200                      Feature featureTo;
201                      try {
202                                    featureTo = (Feature) o;
203                      } catch (ClassCastException e) {
204                                    throw new ClassCastException("FuzzyFeature.compareTo() requires an argument of type Feature.");
205                      }
206                      return FeatureUtils.compareFeatures(this, featureTo);
207             }
208    
209             /**
210              * This will return true if the features are equal and the
211              * sources are the same.  If can't cast argument as a
212              * FuzzyFeature, then throws a java.lang.ClassCastException.
213              */
214             public boolean equals(Object o) throws ClassCastException {
215                      // make sure we got an 'ExactFeature' object
216                      if (GloDBUtils.getClassName(o) != "FuzzyFeature") return false;
217    
218                      // convert object to Feature
219                      FuzzyFeature featureTo;
220                      try {
221                                    featureTo = (FuzzyFeature) o;
222                      } catch (ClassCastException e) {
223                                    throw new ClassCastException("FuzzyFeature.equals() requires an argument of type FuzzyFeature.");
224                      }
225    
226                      // check of same source
227                      if (source != featureTo.source) { return false; }
228    
229                      // check if start, stop, and extensions are all equal
230                      if ((start == featureTo.getStart()) &&
231                                    (startExt == featureTo.getStartExt()) &&
232                                    (stop == featureTo.getStop()) &&
233                                    (stopExt == featureTo.getStopExt())) {
234                                    return true;
235                      } else {
236                                    return false;
237                      }
238             }
239    
240             /** Only returns basic Feature information. */
241             public String toString() {
242                      String out = "Fuzzy Feature (" + source + "): ";
243                      out += "(" + Integer.toString(start) + ", " + Integer.toString(startExt) + ")..";
244                      out += "(" + Integer.toString(stop) + ", " + Integer.toString(stopExt) + ") \n";
245                      return out;
246             }
247    
248             /** Only returns start/stop position information. */
249             public String toStringMin() {
250                      String out = "";
251                      out += "(" + Integer.toString(start) + ", " + Integer.toString(startExt) + ")..";
252                      out += "(" + Integer.toString(stop) + ", " + Integer.toString(stopExt) + ")";
253                      return out;
254             }
255    
256             /** Returns all Feature information. */
257             public String toStringFull() {
258                      String out = "Fuzzy Feature:\n";
259                      //              String out = "Fuzzy Feature (" + source + "): ";
260                      //              out += "(" + Integer.toString(start) + ", " + Integer.toString(startExt) + ")..";
261                      //              out += "(" + Integer.toString(stop) + ", " + Integer.toString(stopExt) + ") \n";
262    
263                      out += "Start: " + Integer.toString(start) + "\n";
264                      out += "StartExt: " + Integer.toString(startExt) + "\n";
265                      out += "Stop: " + Integer.toString(stop) + "\n";
266                      out += "StopExt: " + Integer.toString(stopExt) + "\n";
267    
268                      out += super.toString();  // get attributes and source info
269    
270                      return out;
271             }
272    
273    } // FuzzyFeature.java