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 package org.biojava3.core.sequence.transcription;
023
024 import java.util.List;
025
026 import org.biojava3.core.sequence.compound.AminoAcidCompound;
027 import org.biojava3.core.sequence.compound.NucleotideCompound;
028 import org.biojava3.core.sequence.template.Compound;
029 import org.biojava3.core.sequence.template.CompoundSet;
030 import org.biojava3.core.util.Equals;
031 import org.biojava3.core.util.Hashcoder;
032
033 /**
034 * Provides a way of separating us from the specific {@link IUPACTable} even
035 * though this is the only implementing class for the interface.
036 *
037 * @author ayates
038 */
039 public interface Table {
040
041 List<Codon> getCodons(CompoundSet<NucleotideCompound> nucelotides,
042 CompoundSet<AminoAcidCompound> aminoAcids);
043
044 CompoundSet<Codon> getCodonCompoundSet(
045 final CompoundSet<NucleotideCompound> rnaCompounds,
046 final CompoundSet<AminoAcidCompound> aminoAcidCompounds);
047
048 /**
049 * Returns true if the given compound could have been a start amino acid;
050 * this does not assert if the codon that actually coded for the amino
051 * acid was a start codon. This is as accurate a call as we can make with an
052 * {@link AminoAcidCompound}.
053 */
054 boolean isStart(AminoAcidCompound compound);
055
056 /**
057 * Instance of a Codon which is 3 {@link NucleotideCompound}s, its
058 * corresponding {@link AminoAcidCompound} and if it is a start or stop codon.
059 * The object implements hashCode & equals but according to the nucleotide
060 * compounds & not to the designation of it being a start, stop & amino
061 * acid compound
062 *
063 * @author ayates
064 *
065 */
066 public static class Codon implements Compound {
067
068 private final CaseInsensitiveTriplet triplet;
069 private final boolean start;
070 private final boolean stop;
071 private final AminoAcidCompound aminoAcid;
072 private final String stringified;
073
074 public Codon(CaseInsensitiveTriplet triplet, AminoAcidCompound aminoAcid, boolean start,
075 boolean stop) {
076 this.triplet = triplet;
077 this.start = start;
078 this.stop = stop;
079 this.aminoAcid = aminoAcid;
080 this.stringified = triplet.toString();
081 }
082
083 public Codon(CaseInsensitiveTriplet triplet) {
084 this(triplet, null, false, false);
085 }
086
087 public NucleotideCompound getOne() {
088 return triplet.getOne();
089 }
090
091 public NucleotideCompound getTwo() {
092 return triplet.getTwo();
093 }
094
095 public NucleotideCompound getThree() {
096 return triplet.getThree();
097 }
098
099 public boolean isStart() {
100 return start;
101 }
102
103 public boolean isStop() {
104 return stop;
105 }
106
107 public AminoAcidCompound getAminoAcid() {
108 return aminoAcid;
109 }
110
111 public CaseInsensitiveTriplet getTriplet() {
112 return triplet;
113 }
114
115 @Override
116 public boolean equals(Object obj) {
117 boolean equals = false;
118 if(Equals.classEqual(this, obj)) {
119 Codon casted = (Codon) obj;
120 equals = Equals.equal(getTriplet(), casted.getTriplet()) &&
121 Equals.equal(isStart(), casted.isStart()) &&
122 Equals.equal(isStop(), casted.isStop()) &&
123 Equals.equal(getAminoAcid(), casted.getAminoAcid());
124 }
125 return equals;
126 }
127
128 @Override
129 public int hashCode() {
130 int result = Hashcoder.SEED;
131 result = Hashcoder.hash(result, getTriplet());
132 result = Hashcoder.hash(result, isStop());
133 result = Hashcoder.hash(result, isStart());
134 result = Hashcoder.hash(result, getAminoAcid());
135 return result;
136 }
137
138 @Override
139 public String toString() {
140 return stringified;
141 }
142
143 @Override
144 public boolean equalsIgnoreCase(Compound compound) {
145 return toString().equalsIgnoreCase(compound.toString());
146 }
147
148 @Override
149 public String getDescription() {
150 throw new UnsupportedOperationException("Not supported");
151 }
152
153 @Override
154 public String getLongName() {
155 throw new UnsupportedOperationException("Not supported");
156 }
157
158 @Override
159 public Float getMolecularWeight() {
160 throw new UnsupportedOperationException("Not supported");
161 }
162
163 @Override
164 public String getShortName() {
165 return stringified;
166 }
167
168 @Override
169 public void setDescription(String description) {
170 throw new UnsupportedOperationException("Not supported");
171 }
172
173 @Override
174 public void setLongName(String longName) {
175 throw new UnsupportedOperationException("Not supported");
176 }
177
178 @Override
179 public void setMolecularWeight(Float molecularWeight) {
180 throw new UnsupportedOperationException("Not supported");
181 }
182
183 @Override
184 public void setShortName(String shortName) {
185 throw new UnsupportedOperationException("Not supported");
186 }
187 }
188
189 /**
190 * Class used to hold three nucleotides together and allow for equality
191 * to be assessed in a case insensitive manner.
192 */
193 public static class CaseInsensitiveTriplet {
194
195 private final NucleotideCompound one;
196 private final NucleotideCompound two;
197 private final NucleotideCompound three;
198
199 private transient boolean hashSet = false;
200 private transient int hash;
201 private transient boolean stringSet = false;
202 private transient String stringify;
203
204 public CaseInsensitiveTriplet(NucleotideCompound one,
205 NucleotideCompound two, NucleotideCompound three) {
206 this.one = one;
207 this.two = two;
208 this.three = three;
209
210 }
211
212 public NucleotideCompound getOne() {
213 return one;
214 }
215
216 public NucleotideCompound getTwo() {
217 return two;
218 }
219
220 public NucleotideCompound getThree() {
221 return three;
222 }
223
224 @Override
225 public boolean equals(Object obj) {
226 boolean equals = false;
227 if(Equals.classEqual(this, obj)) {
228 CaseInsensitiveTriplet casted = (CaseInsensitiveTriplet) obj;
229 return toString().equals(casted.toString());
230 }
231 return equals;
232 }
233
234 @Override
235 public int hashCode() {
236 if(!hashSet) {
237 hash = toString().hashCode();
238 hashSet = true;
239 }
240 return hash;
241 }
242
243 @Override
244 public String toString() {
245 if(!stringSet) {
246 stringify = getOne().getUpperedBase() +
247 getTwo().getUpperedBase() +
248 getThree().getUpperedBase();
249 }
250 return stringify;
251 }
252
253 /**
254 * Attempts to provide an int version of this codon which multiplies
255 * each position by
256 */
257 public int intValue() {
258 return (16 * compoundToInt(getOne())) +
259 (4 * compoundToInt(getTwo())) +
260 (compoundToInt(getThree()));
261 }
262
263 public int compoundToInt(NucleotideCompound c) {
264 char b = c.getUpperedBase().charAt(0);
265 return (int)b;
266 // int v = -1;
267 // if('A' == b) {
268 // v = 1;
269 // }
270 // else if('C' == b) {
271 // v = 2;
272 // }
273 // else if('G' == b) {
274 // v = 3;
275 // }
276 // else if('T' == b || 'U' == b) {
277 // v = 4;
278 // }
279 // return v;
280 }
281 }
282 }