/* * 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: 1147 $ by $Author: glycoslave $ on $Date:: 2009-06-04 #$ */ package org.eurocarbdb.sugar; /** *<p> * This class represents modifications that are <em>part of</em> a * {@link Monosaccharide}, as distinct from {@link Substituent}s that * are <em>attached to</em> a Monosaccharide. Defined modification types * are enumerated in the {@link ModificationType} enum. *</p> *<p> * Modifications may either be <em>single-point</em>, that is, occurring * at a single point in the monosaccharide ring, or <em>dual-point</em>, * occurring between 2 points in the monosaccharide ring. Modifications * are also immutable once constructed, although they may be removed * from a Monosaccharide once {@link Monosaccharide#addModification added} * by the {@link Monosaccharide#removeModification} method. *</p> * @author rene * @author mjh added some code and contributed doco. */ public class Modification extends BasicMolecule { //~~~~~~~~~~~~~~~~~~~~~~ STATIC FIELDS ~~~~~~~~~~~~~~~~~~~~~~~~// /** Constant indicating that an attachment position is not known. */ public static final int UNKNOWN_POSITION = 0; /** Constant indicating that an attachment position is not useable. */ private static final int INVALID_POSITION = -1; //~~~~~~~~~~~~~~~~~~~~~~~~~~ FIELDS ~~~~~~~~~~~~~~~~~~~~~~~~~~~// /** The first (lowest-numbered) position to which this * modification is attached. */ private final int position1; // = INVALID_POSITION; /** The second (lowest-numbered) position to which this * modification is attached, if applicable. This value is * set to {@link #INVALID_POSITION} for single point attachments */ private final int position2; // = INVALID_POSITION; /** The modification type of this modification. */ private final ModificationType modification; //~~~~~~~~~~~~~~~~~~~~~~ CONSTRUCTORS ~~~~~~~~~~~~~~~~~~~~~~~~~// /** * Constructs a single-point modification. * @throws IllegalArgumentException if the given modification name * is not a valid/known {@link ModificationType modification type}. */ public Modification( String modificationName, int position ) { this( ModificationType.forName( modificationName ), position ); } /** * Constructs a dual-point modification. * @throws IllegalArgumentException if the given modification name * is not a valid/known {@link ModificationType modification type}. */ public Modification( String modificationName, int position1, int position2 ) { this( ModificationType.forName( modificationName ), position1, position2 ); } /** Constructs a single-point modification. */ public Modification( ModificationType m, int position ) { this.modification = m; //this.setPositionOne( position ); _check_position( position ); this.position1 = position; this.position2 = INVALID_POSITION; } /** Constructs a dual-point modification. */ public Modification( ModificationType m, int position1, int position2 ) { this.modification = m; _check_positions( position1, position2 ); this.position1 = position1; this.position2 = position2; } //~~~~~~~~~~~~~~~~~~~~~~~~~ METHODS ~~~~~~~~~~~~~~~~~~~~~~~~~~~// /** * Gets the first (lowest-numbered) position in the monosaccharide ring * where this modification occurs. */ public int getPositionOne() { return this.position1; } /** * Gets the second (highest-numbered) position in the monosaccharide ring * where this modification occurs. If this is a single-point modification * then calling this method throws an {@link UnsupportedOperationException}. * @see #hasPositionTwo */ public int getPositionTwo() { if ( position2 == INVALID_POSITION ) throw new UnsupportedOperationException( "Modification does not have a second position set; " + "it is a single-point modification" ); return this.position2; } /** * Returns the canonical name of this modification. */ public String getName() { return this.modification.getName(); } /** * Returns true if this is a dual-point modification. */ public boolean hasPositionTwo() { return position2 != INVALID_POSITION; } //~~~~~~~~~~~~~~~~~~~~~~ PRIVATE METHODS ~~~~~~~~~~~~~~~~~~~~~~// /* mjh: no longer settable private void setPositionOne( int position ) { if ( position < Modification.UNKNOWN_POSITION ) throw new IllegalArgumentException( "Invalid value for attach position"); this.position1 = position; } */ /* mjh: no longer settable private void setPositionTwo( int position ) { if ( position < Modification.UNKNOWN_POSITION ) throw new IllegalArgumentException( "Invalid value for attach position"); this.position2 = position; } */ /** Checks position is >= 0 */ private final void _check_position( int position ) { if ( position < Modification.UNKNOWN_POSITION ) throw new IllegalArgumentException( "Invalid value for attach position"); } /** Checks positions are >= 0 and p1 < p2 */ private final void _check_positions( int p1, int p2 ) { _check_position( p1 ); _check_position( p2 ); if ( p1 >= p2 ) throw new IllegalArgumentException( "Position1 argument cannot be >= position2"); } } //end class