/* * EuroCarbDB, a framework for carbohydrate bioinformatics * * Copyright (c) 2006-2009, Eurocarb project, or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * A copy of this license accompanies this distribution in the file LICENSE.txt. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * Last commit: $Rev: 1552 $ by $Author: glycoslave $ on $Date:: 2009-07-20 #$ */ package org.eurocarbdb.sugar; // stdlib imports import java.io.Serializable; import java.util.Iterator; // 3rd party imports import org.apache.log4j.Logger; // eurocarb imports import org.eurocarbdb.sugar.SequenceFormat; import org.eurocarbdb.sugar.SequenceFormatException; // static imports /** *<p> * A very lightweight, fast and sequence format-independent * abstraction of carbohydrate sequences, which includes methods to * retrieve the equivalent {@link Sugar} object of this sequence, * as well as methods to interconvert between different carbohydrate * {@link SequenceFormat}s. *</p><p> * This class is deliberately final and immutable to keep this * implementation as memory & speed efficient as possible. *</p> *<p> *<strong>Usage</strong> *<ul> * <li>To obtain a {@link String} sequence:<pre> * SugarSequence seq = ...; * String the_seq = seq.toString(); * </pre> * </li> * <li>To obtain a {@link String} sequence in a different format:<pre> * SugarSequence seq = ...; * SequenceFormat format = ...; * String the_seq = seq.toString( format ); * </pre> * </li> * <li>To convert a {@link String} from 1 {@link SequenceFormat} to another directly:<pre> * String seq1 = ...; * SequenceFormat from_format = ..., to_format = ...; * String seq2 = SugarSequence.translate( seq1, from_format, to_format ); * </pre> * </li> *</ul> *</p> *<p> * Created 19-Sep-2005. *</p> * * @see #translate(String,SequenceFormat,SequenceFormat) * @see SequenceFormat * @author mjh */ public final class SugarSequence implements Serializable { /** logging handle */ static Logger log = Logger.getLogger( SugarSequence.class ); public static SequenceFormat DEFAULT_SEQUENCE_FORMAT = SequenceFormat.Glycoct; //~~~~~~~~~~~~~~~~~~~~~~~ OBJECT FIELDS ~~~~~~~~~~~~~~~~~~~~~~~// /** Self-explanatory, this is the raw sequence as given by * clients of this class. */ private final String sequence; /** This is the {@link SequenceFormat sequence format} of * the given {@link sequence}. */ private final SequenceFormat format; /** Sugar object parsed from this sequence, lazily instantiated. */ private transient Sugar sugar; //~~~~~~~~~~~~~~~~~~~~~~~~ CONSTRUCTORS ~~~~~~~~~~~~~~~~~~~~~~~// /** * Constructs a SugarSequence from the given sequence string * in the currently set {@link #DEFAULT_SEQUENCE_FORMAT default format}. * @see #DEFAULT_SEQUENCE_FORMAT * @see #Sequence_Parser */ public SugarSequence( String raw_sequence ) throws SequenceFormatException { if ( log.isDebugEnabled() ) { log.debug( "new sugar sequence of " + raw_sequence.length() + " chars, using default format=" + DEFAULT_SEQUENCE_FORMAT.getName() ); } this.sequence = raw_sequence; this.format = DEFAULT_SEQUENCE_FORMAT; } /** * Constructs a SugarSequence from the given sequence string in * the given format. */ public SugarSequence( String raw_sequence, SequenceFormat format ) throws SequenceFormatException { if ( log.isDebugEnabled() ) { log.debug( "new sugar sequence of " + raw_sequence.length() + " chars, using given format=" + format.getName() ); } this.sequence = raw_sequence; this.format = format; } /** Privileged package-access constructor. */ SugarSequence( Sugar s ) { this.sugar = s; this.format = DEFAULT_SEQUENCE_FORMAT; this.sequence = s.toString( format ); } //~~~~~~~~~~~~~~~~~~~~ STATIC METHODS ~~~~~~~~~~~~~~~~~~~~~~~~~// /** * Convenience method for direct conversion of {@link String} * glycan sequence from one {@link SequenceFormat} to another. * eg: *<pre> * String seq_carbbank = ...; * SequenceFormat from_format = SequenceFormat.Carbbank; * SequenceFormat to_format = SequenceFormat.Glycoct; * String seq_glycoct = SugarSequence.translate( seq_carbbank, from_format1, to_format ); *</pre> * @throws SequenceFormatException if passed sequence does not * syntactically conform to the passed format. */ public static String translate( String sequence, SequenceFormat from_format, SequenceFormat to_format ) throws SequenceFormatException { SugarSequence sseq = new SugarSequence( sequence, from_format ); return sseq.toString( to_format ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~ METHODS ~~~~~~~~~~~~~~~~~~~~~~~~~~// /* @see Sequence#getSequenceFormat() */ public SequenceFormat getSequenceFormat() { return format; } /** * Returns a parsed Sugar object representing this sugar sequence. * This Sugar object is lazily instantiated to keep this sequence * class implementation as lightweight as possible. * * @throws SequenceFormatException if the original raw sequence * passed on instantiation is syntactically incorrect. */ public Sugar getSugar() throws SequenceFormatException { if ( sugar == null ) sugar = format.getSugar( sequence ); return sugar; } /** * Returns true only if the sequence string given on * instantiation is syntactically valid. */ public boolean isValid() { try { getSugar(); return true; } catch ( SequenceFormatException e ) { return false; } } /* @see Sequence#iterator() */ public Iterator<Residue> iterator() { return getSugar().iterator(); } /* @see Sequence#toString() */ public String toString() { return this.toString( DEFAULT_SEQUENCE_FORMAT ); } /** * Returns this sequence in the passed {@link SequenceFormat}, * interconverting between formats as necessary. * * @throws SequenceFormatException if there is a problem * parsing the sequence or during conversion. */ public String toString( SequenceFormat format ) throws SequenceFormatException { if ( format == this.format ) return sequence; else return format.getSequence( this.getSugar() ); } } // end class