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 * Created on 01-21-2010
021 */
022
023 package org.biojava3.core.sequence.features;
024
025 import java.util.ArrayList;
026 import java.util.Comparator;
027 import java.util.List;
028 import org.biojava3.core.sequence.location.SequenceLocation;
029 import org.biojava3.core.sequence.template.AbstractSequence;
030 import org.biojava3.core.sequence.template.Compound;
031
032 /**
033 * A feature is currently any descriptive item that can be associated with a sequence position(s)
034 * A feature has a type and a source which is currently a string to allow flexibility for the user
035 * Ideally well defined features should have a class to describe attributes of that feature
036 * @author Scooter Willis <willishf at gmail dot com>
037 */
038 public abstract class AbstractFeature<S extends AbstractSequence<C>, C extends Compound>
039 implements FeatureInterface<S, C> {
040 List<FeatureInterface<S, C>> childrenFeatures = new ArrayList<FeatureInterface<S, C>>();
041 FeatureInterface<S, C> parentFeature;
042 SequenceLocation<S, C> sequenceLocation;
043 String type = "";
044 String source = "";
045 private String description = "";
046 private String shortDescription = "";
047 private Object userObject = null;
048
049 /**
050 * A feature has a type and a source
051 * @param type
052 * @param source
053 */
054 public AbstractFeature(String type,String source){
055 this.type = type;
056 this.source = source;
057 }
058
059 /**
060 * A feature could be a single sequence position like a mutation or a post translational modification of an amino acid.
061 * It could also be the docking interface of N number of amino acids on the surface. The location wold then be a collection
062 * of sequence positions instead of a single sequence position or the begin and end of a sequence seqment.
063 * @return
064 */
065
066 @Override
067 public SequenceLocation<S, C> getLocations() {
068 return sequenceLocation;
069 }
070
071 /**
072 * A feature could be a single sequence position like a mutation or a post translational modification of an amino acid.
073 * It could also be the docking interface of N number of amino acids on the surface. The location wold then be a collection
074 * of sequence positions instead of a single sequence position or the begin and end of a sequence seqment.
075 * @param loc
076 */
077 @Override
078 public void setLocation(SequenceLocation<S, C> loc) {
079 sequenceLocation = loc;
080 }
081
082 /**
083 * The feature type
084 * @return
085 */
086 @Override
087 public String getType() {
088 return type;
089 }
090
091 /**
092 * Set the feature type
093 * @param type
094 */
095 @Override
096 public void setType(String type) {
097 this.type = type;
098 }
099
100 /**
101 * The feature source
102 * @return
103 */
104
105 @Override
106 public String getSource() {
107 return source;
108 }
109
110 /**
111 * Set the feature source
112 * @param source
113 */
114 @Override
115 public void setSource(String source) {
116 this.source = source;
117 }
118
119 /**
120 * A feature can be the child or contained by a parent feature. An example is a Helix feature could contain
121 * children features. A PFAM domain could contain secondary structures.
122 * @param feature
123 */
124 @Override
125 public void setParentFeature(FeatureInterface<S, C> feature) {
126 parentFeature = feature;
127 }
128
129 /**
130 * Get the parent Feature
131 * @return
132 */
133 @Override
134 public FeatureInterface<S, C> getParentFeature() {
135 return parentFeature;
136 }
137
138 /**
139 * Get the children features
140 * @return
141 */
142 @Override
143 public List<FeatureInterface<S, C>> getChildrenFeatures() {
144 return childrenFeatures;
145 }
146
147 /**
148 * Set the children features
149 * @param features
150 */
151 @Override
152 public void setChildrenFeatures(List<FeatureInterface<S, C>> features) {
153 childrenFeatures = features;
154
155 }
156
157 /**
158 * @return the description
159 */
160 public String getDescription() {
161 return description;
162 }
163
164 /**
165 * @param description the description to set
166 */
167 public void setDescription(String description) {
168 this.description = description;
169 }
170
171 /**
172 * @return the shortDescription
173 */
174 public String getShortDescription() {
175 return shortDescription;
176 }
177
178 /**
179 * @param shortDescription the shortDescription to set
180 */
181 public void setShortDescription(String shortDescription) {
182 this.shortDescription = shortDescription;
183 }
184
185 /**
186 * Sort features by start position and then longest length. When features are added
187 * having them sorted by start position and then longest length helps on the layout
188 * of overlapping features so they are delivered in a proper order.
189 */
190
191 public static final Comparator<FeatureInterface<?, ?>> LOCATION_LENGTH = new Comparator<FeatureInterface<?, ?>>() {
192
193 public int compare(FeatureInterface<?, ?> e1, FeatureInterface<?, ?> e2) {
194 double v1 = e1.getLocations().getStart().getPosition();
195 double v2 = e2.getLocations().getStart().getPosition();
196 if (v1 < v2) {
197 return -1;
198 } else if (v1 > v2) {
199 return 1;
200 } else {
201 double end1 = e1.getLocations().getEnd().getPosition();
202 double end2 = e2.getLocations().getEnd().getPosition();
203 if(end1 > end2)
204 return -1;
205 else if(end1 < end2)
206 return 1;
207 else
208 return 0;
209 }
210
211 }
212 };
213
214 /**
215 * Sort features by length. //TODO need to handle cases where features have multiple locations, strand etc
216 *
217 */
218
219 static public final Comparator<FeatureInterface<?, ?>> LENGTH = new Comparator<FeatureInterface<?, ?>>() {
220
221 public int compare(FeatureInterface<?, ?> e1, FeatureInterface<?, ?> e2) {
222 double v1 = Math.abs(e1.getLocations().getEnd().getPosition()- e1.getLocations().getStart().getPosition());
223 double v2 = Math.abs(e2.getLocations().getEnd().getPosition() - e2.getLocations().getStart().getPosition());
224 if (v1 < v2) {
225 return -1;
226 } else if (v1 > v2) {
227 return 1;
228 } else {
229 return 0;
230 }
231
232 }
233 };
234
235 /**
236 * @return the userObject
237 */
238 public Object getUserObject() {
239 return userObject;
240 }
241
242 /**
243 * Allow the user to associate an object with the feature. This way if a feature which is displayed in a GUI
244 * is clicked on the application can then get a user defined object associated with the feature.
245 * @param userObject the userObject to set
246 */
247 public void setUserObject(Object userObject) {
248 this.userObject = userObject;
249 }
250
251 }