/* * 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: 1210 $ by $Author: glycoslave $ on $Date:: 2009-06-12 #$ */ package org.eurocarbdb.application.glycanbuilder; import java.util.*; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import javax.swing.*; import java.util.regex.*; /** This class contains the information about the placement of a residue around its parent in a certain notation. The placement information will be used by the {@link BookingManager} and {@link GlycanRenderer} instances to decide the position of a residue. The placement will define a set of possible position around the parent residue as a list of {@link ResAngle} values. The placement will be matched against parent reside, child residue and linkage information according to the rules defined by a {@link LinkageMatcher} @author Alessio Ceroni (a.ceroni@imperial.ac.uk) */ public class ResiduePlacement { private String rule; private LinkageMatcher matcher; private ResAngle[] positions; private boolean on_border; private boolean sticky; /** Create a default residue placement that will represent a residue in position 0 around its parent */ public ResiduePlacement() { rule = ""; matcher = LinkageMatcher.parse(rule); positions = new ResAngle[1]; on_border = false; sticky = false; } /** Create a default residue placement that will represent a residue in a specified position around its parent */ public ResiduePlacement(ResAngle _position, boolean _on_border, boolean _sticky) { rule = ""; matcher = LinkageMatcher.parse(rule); positions = new ResAngle[1]; positions[0] = _position; on_border = _on_border; sticky = _sticky; } /** Create a new residue placement from an initialization string. @throws Exception if the string is in the wrong format */ public ResiduePlacement(String init) throws Exception { Vector<String> tokens = TextUtils.tokenize(init,"\t"); if( tokens.size()!=4 ) throw new Exception("Invalid string format: " + init); rule = tokens.elementAt(0); matcher = LinkageMatcher.parse(rule); positions = parsePositions(tokens.elementAt(1)); on_border = parseBoolean(tokens.elementAt(2)); sticky = parseBoolean(tokens.elementAt(3)); } static private boolean parseBoolean(String str) { return (str.equals("true") || str.equals("yes")); } static private ResAngle[] parsePositions(String init) throws Exception{ Vector<String> tokens = TextUtils.tokenize(init,","); ResAngle[] ret = new ResAngle[tokens.size()]; for( int i=0; i<tokens.size(); i++ ) ret[i] = new ResAngle(tokens.elementAt(i)); return ret; } /** Return a copy of this object */ public ResiduePlacement clone() { ResiduePlacement ret = new ResiduePlacement(); ret.rule = this.rule; ret.matcher = LinkageMatcher.parse(rule); ret.positions = this.positions; ret.on_border = this.on_border; ret.sticky = this.sticky; return ret; } /** Return a copy of this object modified for the case that the parent has the sticky flag set */ public ResiduePlacement getIfSticky() { ResiduePlacement ret = new ResiduePlacement(); ret.rule = this.rule; ret.matcher = this.matcher; if( this.on_border ) { ret.on_border = true; ret.positions = this.positions; } else { ret.on_border = false; ret.positions = new ResAngle[] {new ResAngle(0)}; } ret.sticky = true; return ret; } /** Return the rule used to generate the {@link LinkageMatcher} */ public String getRule() { return rule; } /** Return the {@link LinkageMatcher} used to match the placement to a specific residue and its context */ public LinkageMatcher getMatcher() { return matcher; } /** Return <code>true</code> if the placements matches a specific residue and its context @param parent the parent residue @param link the linkage to the parent @param child the residue for which the placement should be determined */ public boolean matches(Residue parent, Linkage link, Residue child) { return matcher.matches(parent,link,child); } /** The list of positions in which the residue could be placed */ public ResAngle[] getPositions() { return positions; } /** The list of positions in which the residue could be placed represented as a comma separated list of tokens in a string */ public String getStringPositions() { StringBuilder ss = new StringBuilder(); for( int i=0; i<positions.length; i++ ) { if( i>0 ) ss.append(","); ss.append(positions[i]); } return ss.toString(); } /** Return <code>true</code> if this placement allows a specific position for a residuex */ public boolean hasPosition(ResAngle pos) { for( int i=0; i<positions.length; i++ ) if( positions[i].equals(pos) ) return true; return false; } /** Return <code>true</code> if the residue should be placed on the border of its parent @see GlycanRenderer */ public boolean isOnBorder() { return on_border; } /** Return <code>true</code> if all the residues in the subtree should be placed in position 0 @see GlycanRenderer */ public boolean isSticky() { return sticky; } /* public void toggleSticky() { sticky = !sticky; } */ public String toString() { return rule + " " + getStringPositions() + " " + on_border + " " + sticky; } }