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 * @author Richard Holland
023 *
024 *
025 */
026package org.biojava.nbio.core.sequence.template;
027
028import org.biojava.nbio.core.sequence.AccessionID;
029import org.biojava.nbio.core.util.Equals;
030
031import java.util.Iterator;
032import java.util.List;
033
034public class SequenceProxyView<C extends Compound> implements SequenceView<C> {
035
036        private Integer bioStart;
037        private Integer bioEnd;
038        private Sequence<C> sequence;
039
040        public SequenceProxyView() {
041        }
042
043        public SequenceProxyView(Sequence<C> sequence) {
044                this(sequence, 1, sequence.getLength());
045        }
046
047        /**
048         * Main constructor for working with SequenceProxyViews
049         *
050         * @param sequence Sequence to proxy
051         * @param bioStart Start; cannot be less than 1
052         * @param bioEnd End; cannot be greater than the sequence length
053         */
054        public SequenceProxyView(Sequence<C> sequence, Integer bioStart, Integer bioEnd) {
055                this.sequence = sequence;
056                setBioStart(bioStart);
057                setBioEnd(bioEnd);
058        }
059
060        @Override
061        public Sequence<C> getViewedSequence() {
062                return sequence;
063        }
064
065        @Override
066        public String getSequenceAsString() {
067                return SequenceMixin.toString(this);
068        }
069
070        @Override
071        public List<C> getAsList() {
072                return SequenceMixin.toList(this);
073        }
074
075        @Override
076        public boolean equals(Object o) {
077
078                if(! Equals.classEqual(this, o)) {
079                        return false;
080                }
081
082                Sequence<C> other = (Sequence<C>)o;
083
084                return sequence.equals(other);
085        }
086
087        @Override
088        public int hashCode(){
089                String s = getSequenceAsString();
090                return s.hashCode();
091        }
092
093        @Override
094        public C getCompoundAt(int position) {
095                return getViewedSequence().getCompoundAt((getBioStart() + position) - 1);
096        }
097
098        @Override
099        public int getIndexOf(C compound) {
100                return SequenceMixin.indexOf(this, compound);
101        }
102
103        @Override
104        public int getLastIndexOf(C compound) {
105                return SequenceMixin.lastIndexOf(this, compound);
106        }
107
108        @Override
109        public int getLength() {
110                return (getBioEnd() - getBioStart()) + 1;
111        }
112
113        @Override
114        public CompoundSet<C> getCompoundSet() {
115                return getViewedSequence().getCompoundSet();
116        }
117
118        @Override
119        public SequenceView<C> getSubSequence(final Integer bioStart, final Integer bioEnd) {
120                return new SequenceProxyView<C>(this, bioStart, bioEnd);
121        }
122
123        @Override
124        public Iterator<C> iterator() {
125                return new SequenceMixin.SequenceIterator<C>(this);
126        }
127
128        @Override
129        public AccessionID getAccession() {
130                return getViewedSequence().getAccession();
131        }
132
133        /**
134         * @return the bioStart
135         */
136        @Override
137        public Integer getBioStart() {
138                return bioStart;
139        }
140
141        /**
142         * @param bioStart the bioStart to set
143         */
144        public void setBioStart(Integer bioStart) {
145                if (bioStart < 1) {
146                        throw new IllegalArgumentException("The given start "
147                                        + bioStart + " is less than 1; cannot index less than 1");
148                }
149                this.bioStart = bioStart;
150        }
151
152        /**
153         * @return the bioEnd
154         */
155        @Override
156        public Integer getBioEnd() {
157                return bioEnd;
158        }
159
160        /**
161         * @param bioEnd the bioEnd to set
162         */
163        public void setBioEnd(Integer bioEnd) {
164                if(sequence == null) {
165                        throw new NullPointerException("No sequence given before setting the end coordinate; cannot be done");
166                }
167                // had a bug in the code that allowed this to work. The length of a any exon or cds sequence was always the length of the
168                //parent sequence. Sequence class doesn't have bioStart and bioEnd exposed to do a proper comparison of getting
169                // a subsequence. Januar-20=2011 Scooter
170         //   if (bioEnd > sequence.getLength()) {
171         //       throw new IllegalArgumentException("The given end "
172         //               + bioEnd + " is greater than sequence length"
173         //               + sequence.getLength());
174         //   }
175                this.bioEnd = bioEnd;
176        }
177
178        @Override
179        public int countCompounds(C... compounds) {
180                return SequenceMixin.countCompounds(this, compounds);
181        }
182
183        @Override
184        public SequenceView<C> getInverse() {
185                return SequenceMixin.inverse(this);
186        }
187}