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.bio.program.fastq;
022
023/**
024 * Fluent builder API for creating FASTQ formatted sequences.
025 *
026 * @since 1.7.1
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 1.9.5
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}