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 */
021package org.biojava.nbio.genome.io.fastq;
022
023/**
024 * Fluent builder API for creating FASTQ formatted sequences.
025 *
026 * @since 3.0.3
027 */
028public final class FastqBuilder
029{
030        /** Description for this FASTQ formatted sequence builder. */
031        private String description;
032
033        /** Sequence for this FASTQ formatted sequence builder. */
034        private StringBuilder sequence;
035
036        /** Quality scores for this FASTQ formatted sequence builder. */
037        private StringBuilder quality;
038
039        /** FASTQ sequence format variant for this FASTQ formatted sequence builder. */
040        private FastqVariant variant = DEFAULT_VARIANT;
041
042        /** Default FASTQ sequence format variant, <code>FastqVariant.FASTQ_SANGER</code>. */
043        public static final FastqVariant DEFAULT_VARIANT = FastqVariant.FASTQ_SANGER;
044
045
046        /**
047         * Create a new FASTQ formatted sequence builder.
048         */
049        public FastqBuilder()
050        {
051                // empty
052        }
053
054        /**
055         * Create a new FASTQ formatted sequence builder configured
056         * from the specified FASTQ formatted sequence.
057         *
058         * @since 6.0.0
059         * @param fastq FASTQ formatted sequence, must not be null
060         */
061        public FastqBuilder(final Fastq fastq)
062        {
063                if (fastq == null)
064                {
065                        throw new IllegalArgumentException("fastq must not be null");
066                }
067                withDescription(fastq.getDescription());
068                withSequence(fastq.getSequence());
069                withQuality(fastq.getQuality());
070                withVariant(fastq.getVariant());
071        }
072
073
074        /**
075         * Return the description for this FASTQ formatted sequence builder.
076         *
077         * @return the description for this FASTQ formatted sequence builder
078         */
079        public String getDescription()
080        {
081                return description;
082        }
083
084        /**
085         * Return this FASTQ formatted sequence builder configured with the specified description.
086         *
087         * @param description description for this FASTQ formatted sequence builder, must not be null
088         * @return this FASTQ formatted sequence builder configured with the specified description
089         */
090        public FastqBuilder withDescription(final String description)
091        {
092                if (description == null)
093                {
094                        throw new IllegalArgumentException("description must not be null");
095                }
096                this.description = description;
097                return this;
098        }
099
100        /**
101         * Return this FASTQ formatted sequence builder configured with the specified sequence.
102         *
103         * @param sequence sequence for this FASTQ formatted sequence builder, must not be null
104         * @return this FASTQ formatted sequence builder configured with the specified sequence
105         */
106        public FastqBuilder withSequence(final String sequence)
107        {
108                if (sequence == null)
109                {
110                        throw new IllegalArgumentException("sequence must not be null");
111                }
112                if (this.sequence == null)
113                {
114                        this.sequence = new StringBuilder(sequence.length());
115                }
116                this.sequence.replace(0, this.sequence.length(), sequence);
117                return this;
118        }
119
120        /**
121         * Return this FASTQ formatted sequence builder configured with the specified sequence
122         * appended to its current sequence.
123         *
124         * @param sequence sequence to append to the sequence for this FASTQ formatted sequence builder, must not be null
125         * @return this FASTQ formatted sequence builder configured with the specified sequence
126         *    appended to its current sequence
127         */
128        public FastqBuilder appendSequence(final String sequence)
129        {
130                if (sequence == null)
131                {
132                        throw new IllegalArgumentException("sequence must not be null");
133                }
134                if (this.sequence == null)
135                {
136                        this.sequence = new StringBuilder(sequence.length());
137                }
138                this.sequence.append(sequence);
139                return this;
140        }
141
142        /**
143         * Return this FASTQ formatted sequence builder configured with the specified quality scores.
144         *
145         * @param quality quality scores for this FASTQ formatted sequence builder, must not be null
146         * @return this FASTQ formatted sequence builder configured with the specified quality scores
147         */
148        public FastqBuilder withQuality(final String quality)
149        {
150                if (quality == null)
151                {
152                        throw new IllegalArgumentException("quality must not be null");
153                }
154                if (this.quality == null)
155                {
156                        this.quality = new StringBuilder(quality.length());
157                }
158                this.quality.replace(0, this.quality.length(), quality);
159                return this;
160        }
161
162        /**
163         * Return this FASTQ formatted sequence builder configured with the specified quality scores
164         * appended to its current quality scores.
165         *
166         * @param quality quality scores to append to the quality scores for this FASTQ formatted sequence
167         *    builder, must not be null
168         * @return this FASTQ formatted sequence builder configured with the specified quality scores
169         *    appended to its current quality scores
170         */
171        public FastqBuilder appendQuality(final String quality)
172        {
173                if (quality == null)
174                {
175                        throw new IllegalArgumentException("quality must not be null");
176                }
177                if (this.quality == null)
178                {
179                        this.quality = new StringBuilder(quality.length());
180                }
181                this.quality.append(quality);
182                return this;
183        }
184
185        /**
186         * Return true if the sequence and quality scores for this FASTQ formatted sequence builder are equal in length.
187         *
188         * @return true if the sequence and quality scores for this FASTQ formatted sequence builder are equal in length
189         */
190        public boolean sequenceAndQualityLengthsMatch()
191        {
192                if (sequence == null && quality == null)
193                {
194                        return true;
195                }
196                if ((sequence != null && quality == null) || (sequence == null && quality != null))
197                {
198                        return false;
199                }
200                return sequence.length() == quality.length();
201        }
202
203        /**
204         * Return this FASTQ formatted sequence builder configured with the specified FASTQ sequence format variant.
205         *
206         * @param variant FASTQ sequence format variant for this FASTQ formatted sequence builder, must not be null
207         * @return this FASTQ formatted sequence builder configured with the specified FASTQ sequence format variant
208         */
209        public FastqBuilder withVariant(final FastqVariant variant)
210        {
211                if (variant == null)
212                {
213                        throw new IllegalArgumentException("variant must not be null");
214                }
215                this.variant = variant;
216                return this;
217        }
218
219        /**
220         * Build and return a new FASTQ formatted sequence configured from the properties of this builder.
221         *
222         * @return a new FASTQ formatted sequence configured from the properties of this builder
223         * @throws IllegalStateException if the configuration of this builder results in an illegal state
224         */
225        public Fastq build()
226        {
227                if (description == null)
228                {
229                        throw new IllegalStateException("description must not be null");
230                }
231                if (sequence == null)
232                {
233                        throw new IllegalStateException("sequence must not be null");
234                }
235                if (quality == null)
236                {
237                        throw new IllegalStateException("quality must not be null");
238                }
239                if (!sequenceAndQualityLengthsMatch())
240                {
241                        throw new IllegalStateException("sequence and quality scores must be the same length");
242                }
243                Fastq fastq = new Fastq(description, sequence.toString(), quality.toString(), variant);
244                return fastq;
245        }
246}