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    /**
056     * Return the description for this FASTQ formatted sequence builder.
057     *
058     * @return the description for this FASTQ formatted sequence builder
059     */
060    public String getDescription()
061    {
062        return description;
063    }
064
065    /**
066     * Return this FASTQ formatted sequence builder configured with the specified description.
067     *
068     * @param description description for this FASTQ formatted sequence builder, must not be null
069     * @return this FASTQ formatted sequence builder configured with the specified description
070     */
071    public FastqBuilder withDescription(final String description)
072    {
073        if (description == null)
074        {
075            throw new IllegalArgumentException("description must not be null");
076        }
077        this.description = description;
078        return this;
079    }
080
081    /**
082     * Return this FASTQ formatted sequence builder configured with the specified sequence.
083     *
084     * @param sequence sequence for this FASTQ formatted sequence builder, must not be null
085     * @return this FASTQ formatted sequence builder configured with the specified sequence
086     */
087    public FastqBuilder withSequence(final String sequence)
088    {
089        if (sequence == null)
090        {
091            throw new IllegalArgumentException("sequence must not be null");
092        }
093        if (this.sequence == null)
094        {
095            this.sequence = new StringBuilder(sequence.length());
096        }
097        this.sequence.replace(0, this.sequence.length(), sequence);
098        return this;
099    }
100
101    /**
102     * Return this FASTQ formatted sequence builder configured with the specified sequence
103     * appended to its current sequence.
104     *
105     * @param sequence sequence to append to the sequence for this FASTQ formatted sequence builder, must not be null
106     * @return this FASTQ formatted sequence builder configured with the specified sequence
107     *    appended to its current sequence
108     */
109    public FastqBuilder appendSequence(final String sequence)
110    {
111        if (sequence == null)
112        {
113            throw new IllegalArgumentException("sequence must not be null");
114        }
115        if (this.sequence == null)
116        {
117            this.sequence = new StringBuilder(sequence.length());
118        }
119        this.sequence.append(sequence);
120        return this;
121    }
122
123    /**
124     * Return this FASTQ formatted sequence builder configured with the specified quality scores.
125     *
126     * @param quality quality scores for this FASTQ formatted sequence builder, must not be null
127     * @return this FASTQ formatted sequence builder configured with the specified quality scores
128     */
129    public FastqBuilder withQuality(final String quality)
130    {
131        if (quality == null)
132        {
133            throw new IllegalArgumentException("quality must not be null");
134        }
135        if (this.quality == null)
136        {
137            this.quality = new StringBuilder(quality.length());
138        }
139        this.quality.replace(0, this.quality.length(), quality);
140        return this;
141    }
142
143    /**
144     * Return this FASTQ formatted sequence builder configured with the specified quality scores
145     * appended to its current quality scores.
146     *
147     * @param quality quality scores to append to the quality scores for this FASTQ formatted sequence
148     *    builder, must not be null
149     * @return this FASTQ formatted sequence builder configured with the specified quality scores
150     *    appended to its current quality scores
151     */
152    public FastqBuilder appendQuality(final String quality)
153    {
154        if (quality == null)
155        {
156            throw new IllegalArgumentException("quality must not be null");
157        }
158        if (this.quality == null)
159        {
160            this.quality = new StringBuilder(quality.length());
161        }
162        this.quality.append(quality);
163        return this;
164    }
165
166    /**
167     * Return true if the sequence and quality scores for this FASTQ formatted sequence builder are equal in length.
168     *
169     * @return true if the sequence and quality scores for this FASTQ formatted sequence builder are equal in length
170     */
171    public boolean sequenceAndQualityLengthsMatch()
172    {
173        if (sequence == null && quality == null)
174        {
175            return true;
176        }
177        if ((sequence != null && quality == null) || (sequence == null && quality != null))
178        {
179            return false;
180        }
181        return sequence.length() == quality.length();
182    }
183
184    /**
185     * Return this FASTQ formatted sequence builder configured with the specified FASTQ sequence format variant.
186     *
187     * @param variant FASTQ sequence format variant for this FASTQ formatted sequence builder, must not be null
188     * @return this FASTQ formatted sequence builder configured with the specified FASTQ sequence format variant
189     */
190    public FastqBuilder withVariant(final FastqVariant variant)
191    {
192        if (variant == null)
193        {
194            throw new IllegalArgumentException("variant must not be null");
195        }
196        this.variant = variant;
197        return this;
198    }
199
200    /**
201     * Build and return a new FASTQ formatted sequence configured from the properties of this builder.
202     *
203     * @return a new FASTQ formatted sequence configured from the properties of this builder
204     * @throws IllegalStateException if the configuration of this builder results in an illegal state
205     */
206    public Fastq build()
207    {
208        if (description == null)
209        {
210            throw new IllegalStateException("description must not be null");
211        }
212        if (sequence == null)
213        {
214            throw new IllegalStateException("sequence must not be null");
215        }
216        if (quality == null)
217        {
218            throw new IllegalStateException("quality must not be null");
219        }
220        if (!sequenceAndQualityLengthsMatch())
221        {
222            throw new IllegalStateException("sequence and quality scores must be the same length");
223        }
224        Fastq fastq = new Fastq(description, sequence.toString(), quality.toString(), variant);
225        return fastq;
226    }
227}