/*
* 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.resourcesdb.monosaccharide;
import java.util.ArrayList;
import java.util.HashMap;
import org.eurocarbdb.resourcesdb.ResourcesDbException;
import org.eurocarbdb.resourcesdb.template.BasetypeTemplate;
import org.eurocarbdb.resourcesdb.template.BasetypeTemplateContainer;
public class Stereocode implements Cloneable {
//*** standard stereocode symbols: ***
public static final char StereoD = '2';
public static final char StereoL = '1';
public static final char StereoXD = '4';
public static final char StereoXL = '3';
public static final char StereoX = 'x';
public static final char StereoN = '0';
//*** extended stereocode symbols: ***
public static final char ExtStereoDeoxy = 'd';
public static final char ExtStereoEnOH = 'n';
public static final char ExtStereoEnDeoxy = 'e';
public static final char ExtStereoEnX = 'E';
public static final char ExtStereoCH2OH = 'h';
public static final char ExtStereoCH3 = 'm';
public static final char ExtStereoAcid = 'a';
public static final char ExtStereoCarbonyl = 'o';
public static final char ExtStereoSp2 = 's';
public static final char ExtStereoYn = 'y';
public static final char ExtStereoKeto = 'k';
public static final char ExtStereoUnknown = 'x';
private String stereoStr;
public static final String SUBTYPESTR = "subtype";
public static final String BASETYPESTR = "basetype";
//*****************************************************************************
//*** constructors: ***********************************************************
//*****************************************************************************
/**
* Constructor, creates a stereocode initialized with a given stereo string
* @param code: stereocode string
*/
public Stereocode(String code) {
setStereoStr(code);
}
/**
* Constructor, creates an empty stereocode
*/
public Stereocode() {
setStereoStr("");
}
//*****************************************************************************
//*** getters/setters: ********************************************************
//*****************************************************************************
/**
* Get the stereocode string.
* @return the stereocode string
*/
public String getStereoStr() {
return stereoStr;
}
/**
* Set the stereocode string.
* @param stereocode: The string to set.
*/
public void setStereoStr(String stereocode) {
this.stereoStr = stereocode;
}
//*****************************************************************************
//*** methods to manipulate the stereocode: ***********************************
//*****************************************************************************
/**
* Alter a stereocode string in a way as it would result from rotating an alditol residue by 180°.
* @param stereo: The stereocode string to be altered.
* @return The adjusted stereocode string
*/
public static String rotateStereoString(String stereo) {
String rotStereo = "";
for(int i = stereo.length() - 1; i >= 0; i--) {
rotStereo += stereo.substring(i, i + 1);
}
return(changeDLinStereoString(rotStereo));
}
/**
* Alter the stereocode in a way as it would result from rotating an alditol residue by 180°.
*/
public void rotate() {
setStereoStr(Stereocode.rotateStereoString(getStereoStr()));
}
/**
* Change a stereocode string in D configuration to one in L configuration and vice versa.
* @param stereoIn: The stereocode string to be altered.
* @return The altered stereocode string.
*/
public static String changeDLinStereoString(String stereoIn) {
String stereoOut = "";
for(int i = 0; i < stereoIn.length(); i++) {
if(stereoIn.charAt(i) == StereoD) {
stereoOut += StereoL;
} else if(stereoIn.charAt(i) == StereoL) {
stereoOut += StereoD;
} else if(stereoIn.charAt(i) == StereoXD) {
stereoOut += StereoXL;
} else if(stereoIn.charAt(i) == StereoXL) {
stereoOut += StereoXD;
} else {
stereoOut += stereoIn.charAt(i);
}
}
return(stereoOut);
}
/**
* Change a stereocode in D configuration to one in L configuration and vice versa.
*/
public void changeDL() {
setStereoStr(Stereocode.changeDLinStereoString(getStereoStr()));
}
/**
* Change relative D positions in a stereo string to relative L positions and vice versa.
* Note: Absolute D or L positions are not changed by this method!
* @param stereoIn: The stereocode string to be altered.
* @return The altered stereocode string.
*/
public static String changeRelativeDLinStereoString(String stereoIn) {
String stereoOut = "";
for(int i = 0; i < stereoIn.length(); i++) {
if(stereoIn.charAt(i) == StereoXD) {
stereoOut += StereoXL;
} else if(stereoIn.charAt(i) == StereoXL) {
stereoOut += StereoXD;
} else {
stereoOut += stereoIn.charAt(i);
}
}
return(stereoOut);
}
/**
* Change relative D positions in this Stereocode to relative L positions and vice versa
*/
public void changeRelativeDL() {
this.setStereoStr(Stereocode.changeRelativeDLinStereoString(this.getStereoStr()));
}
/**
* Translate a stereocode string in absolute configuration into one in relative configuration
* @param stereoIn: The stereocode string to be translated.
* @return: The translated stereocode string.
* @throws ResourcesDbException in case the stereocode string contains characters that do not encode any configuration status
*/
public static String absoluteToRelative(String stereoIn) throws ResourcesDbException {
String stereoOut = "";
for(int i = 0; i < stereoIn.length(); i++) {
stereoOut += StereoConfiguration.stereosymbolAbsoluteToRelative(stereoIn.charAt(i));
}
return(stereoOut);
}
/**
* Translate a stereocode string in relative configuration into one in absolute configuration.
* If both absolute and relative configurations are present in the stereocode string, the absolute positions are kept as they are.
* @param stereoIn: The stereocode string to be translated.
* @return: The translated stereocode string.
* @throws ResourcesDbException in case the stereocode string contains characters that do not encode any configuration status
*/
public static String relativeToAbsolute(String stereoIn) throws ResourcesDbException {
String stereoOut = "";
for(int i = 0; i < stereoIn.length(); i++) {
stereoOut += StereoConfiguration.stereosymbolRelativeToAbsolute(stereoIn.charAt(i));
}
return(stereoOut);
}
/**
* Check, if a stereo string contains both absolute and relative configuration positions
* @param stereo: the stereo string to be checked
* @return
* @throws ResourcesDbException in case the stereo string contains characters that do not encode any configuration status
*/
public static boolean stereoStringContainsAbsoluteAndRelative(String stereo) throws ResourcesDbException {
boolean containsAbsolute = false;
boolean containsRelative = false;
for(int i = 0; i < stereo.length(); i++) {
StereoConfiguration c = StereoConfiguration.forStereosymbol(stereo.charAt(i));
if(c.equals(StereoConfiguration.Dexter) || c.equals(StereoConfiguration.Laevus)) {
containsAbsolute = true;
}
if(c.equals(StereoConfiguration.XDexter) || c.equals(StereoConfiguration.XLaevus)) {
containsRelative = true;
}
}
return(containsAbsolute && containsRelative);
}
/**
* Check, if a stereo string has at least one relative configuration position
* @param stereo: the stereo string to be checked
* @return
*/
public static boolean stereoStringHasRelativePosition(String stereo) {
for(int i = 0; i < stereo.length(); i++) {
StereoConfiguration c;
try {
c = StereoConfiguration.forStereosymbol(stereo.charAt(i));
} catch (ResourcesDbException e) {
continue;
}
if(c.equals(StereoConfiguration.XDexter) || c.equals(StereoConfiguration.XLaevus)) {
return(true);
}
}
return(false);
}
/**
* Check, if this Stereocode has at least one relative configuration position
* @return
*/
public boolean hasRelativePosition() {
return Stereocode.stereoStringHasRelativePosition(this.getStereoStr());
}
/**
* Get the configuration of a monosaccharide or a monosaccharide subpart based on a stereocode string
* Note: a relative configuration (XD/XL) is handled as an unknown one here
* @param stereo: the stereostring from which the configuration is determined
* @return the configuration (D/L/X)
*/
public static StereoConfiguration getConfigurationFromStereoString(String stereo) {
stereo = stereo.replaceAll("" + StereoN, "");
char configCode = ' ';
if(stereo.length() == 0) {
return(StereoConfiguration.Nonchiral);
}
if(stereo.length() < 4) {
configCode = stereo.charAt(stereo.length() - 1);
} else {
configCode = stereo.charAt(3);
}
if(configCode == StereoD) {
return(StereoConfiguration.Dexter);
} else if(configCode == StereoL) {
return(StereoConfiguration.Laevus);
} else {
return(StereoConfiguration.Unknown);
}
}
/**
* Get the configuration of a monosaccharide trivial name based on a stereocode string
* This method differs from "getConfigurationFromStereostring(String stereo)" insofar that the configuration is always determined from the last non-chiral center, no matter how long the stereo string is.
* This is needed to correctly assign the configuration of trivial names that cover more than 4 stereocenters.
* Note: a relative configuration (XD/XL) is handled as an unknown one here
* @param stereo: the stereostring from which the configuration is determined
* @return the configuration (D/L/X)
*/
public static StereoConfiguration getTrivialnameConfigurationFromStereoString(String stereo) {
stereo = stereo.replaceAll("" + StereoN, "");
char configCode = ' ';
if(stereo.length() == 0) {
return(StereoConfiguration.Nonchiral);
}
configCode = stereo.charAt(stereo.length() - 1);
if(configCode == StereoD) {
return(StereoConfiguration.Dexter);
} else if(configCode == StereoL) {
return(StereoConfiguration.Laevus);
} else {
return(StereoConfiguration.Unknown);
}
}
/**
* Delete all non-chiral or unknown positions from a stereocode string
* @param stereo
* @return
*/
public static String getChiralOnlyStereoString(String stereo) {
String stereoOut = "";
for(int i = 0; i < stereo.length(); i++) {
char symbol = stereo.charAt(i);
if(symbol == StereoD || symbol == StereoL || symbol == StereoXD || symbol == StereoXL) {
stereoOut += symbol;
}
}
return(stereoOut);
}
public static String maskAnomerInStereoString(String stereo, Basetype bt) throws ResourcesDbException {
if(stereo.length() != bt.getSize()) {
throw new ResourcesDbException("stereostring length (" + stereo.length() + ") does not match basetype size (" + bt.getSize() + ")");
}
if(bt.getRingStart() > 0 && bt.getRingStart() <= bt.getSize()) {
stereo = Stereocode.setPositionInStereoString(stereo, Stereocode.StereoN, bt.getRingStart());
}
return stereo;
}
/**
* Get the correct basetype template for a monosaccharide based on its stereocode string.
* If the template encodes a monosaccharide smaller than the given one (due to loss of stereochemistry), it is returned in the SUBTYPESTR field of the HashMap and the BASETYPESTR field contains the superclass template.
* Otherwise, the BASETYPESTR field contains the template and the SUBTYPESTR field is null.
* @param stereo The stereocode of the monosaccharide
* @param ms The monosaccharide which the stereocode belongs to
* @param container a BasetypeTemplateContainer to get the templates
* @return HashMap with 2 fields, addressed by the labels Stereocode.BASETYPESTR and Stereocode.SUBTYPESTR
*/
public static HashMap<String, BasetypeTemplate> getBasetypeFromStereoString(String stereo, Monosaccharide ms, BasetypeTemplateContainer container) throws ResourcesDbException {
if(stereo.length() == ms.getSize()/* && ms.getRingStart() > 0 && ms.getRingStart() <= ms.getSize()*/) {
//*** make sure configuration of anomeric is not taken into account for basetype determination ***
stereo = ms.getStereoStrWithoutAnomeric();
}
stereo = getChiralOnlyStereoString(stereo);
if(stereo.length() > 4) {
stereo = stereo.substring(0, 4);
}
HashMap<String, BasetypeTemplate> resultMap = new HashMap<String, BasetypeTemplate>();
BasetypeTemplate msTmpl = container.getBasetypeTemplateByStereoString(stereo);
if(msTmpl == null) {
throw new MonosaccharideException("Cannot get basetype from stereocode " + stereo);
}
if(msTmpl.getSize() == ms.getSize()) {
resultMap.put(Stereocode.BASETYPESTR, msTmpl);
resultMap.put(Stereocode.SUBTYPESTR, null);
} else {
resultMap.put(Stereocode.BASETYPESTR, container.getSuperclassTemplateBySize(ms.getSize()));
resultMap.put(Stereocode.SUBTYPESTR, msTmpl);
}
return(resultMap);
}
/**
* Get the basetype for a monosaccharide (or for a monosaccharide subpart) based on its stereocode string.
* In contrast to getBasetypeFromStereocode() it is not checked if the determined basetype corresponds to the size of the monosaccharide, i.e. no basetype / subtype are returned.
* The anomeric must not be included in the stereocode.
* @param stereo The stereocode to be checked
* @param container a BasetypeTemplateContainer to get the needed templates
* @return The MonosaccharideTemplate corresponding to the given stereocode string.
* @throws ResourcesDbException in case no template matches the stereocode string.
*/
public static BasetypeTemplate getBasetypeFromStereoStringNoSizecheck(String stereo, BasetypeTemplateContainer container) throws ResourcesDbException {
stereo = getChiralOnlyStereoString(stereo);
if(stereo.length() > 4) {
stereo = stereo.substring(0, 4);
}
BasetypeTemplate msTmpl = container.getBasetypeTemplateByStereoString(stereo);
return(msTmpl);
}
/**
* Get the root templates for a given stereocode string.
* "root templates" are monosaccharide templates, from which a monosaccharide can be derived (can be more than one in case of loss of stereochemistry)
* @param stereo Stereocode (stereo-relevant positions (2 to n-1) only)
* @param container a BasetypeTemplateContainer to get the needed templates
* @return ArrayList of Monosaccharide Templates which match the stereocode
* @throws ResourcesDbException in case template lists are not set
*/
public static ArrayList<BasetypeTemplate> getRootTemplatesByStereoString(String stereo, BasetypeTemplateContainer container) throws ResourcesDbException {
ArrayList<BasetypeTemplate> rootList = new ArrayList<BasetypeTemplate>();
//*** get stereorelevant positions and replace non-chiral positions by dots for regular expression matching: ***
stereo.replaceAll("[" + StereoX + StereoN + "]", ".");
//*** find templates with matching stereocodes: ***
String stereoDL = changeDLinStereoString(stereo);
ArrayList<String> basetypeList = container.getBasetypeListSpecific();
for(int i = 0; i < basetypeList.size(); i++) {
BasetypeTemplate tmpl = container.getBasetypeTemplateByName(basetypeList.get(i));
if(tmpl.getStereocode().matches(stereo) || tmpl.getStereocode().matches(stereoDL)) {
rootList.add(tmpl);
}
}
return(rootList);
}
/**
* Expand a stereocode string that contains only the chiral positions to a stereocode string representing the entire monosaccharide.
* Nonchiral positions are inserted into the given stereocode string.
* @param stereo Stereocode with chiral positions only. In case of ring forms, the anomeric must NOT be contained in the stereocode.
* @param ms Monosaccharide, to which the stereocode string belongs
* @return full stereocode string of the monosaccharide (positions 1 to n), chirality resulting from anomeric is not set yet
*/
public static String expandChiralonlyStereoString(String stereo, Monosaccharide ms) throws MonosaccharideException {
String stereoOut = "";
stereoOut += StereoConfiguration.Nonchiral.getStereosymbol(); //*** position 1 is non-chiral by default (if applicable, chirality resulting from anomeric is set later) ***
if(ms.getRingStart() == 2) {
stereoOut += StereoConfiguration.Nonchiral.getStereosymbol();
}
stereoOut += stereo;
stereoOut += StereoConfiguration.Nonchiral.getStereosymbol();
ArrayList<Integer> stereoLossPos = ms.getStereolossPositions(); //*** (positions list is already sorted, therefore no further sorting is necessary here) ***
if(stereoLossPos.contains(new Integer(0))) { //*** no stereocode can be built if a position of a loss of stereochemistry is unknown ***
throw new MonosaccharideException("Cannot assign stereochemistry due to unknown position of a modification that causes loss of stereochemistry");
}
for(int i = 0; i < stereoLossPos.size(); i++) {
int position = stereoLossPos.get(i);
if(position <= 0) {
throw new MonosaccharideException("Error in setting stereocode: position out of range (" + position + ").");
}
if(position == ms.getRingStart() && position == 2) {
continue; //*** position already set above ***
}
if(position == 1 || position == ms.getSize()) {
continue; //*** first and last position are always non-chiral ***
}
if(position > stereoOut.length()) {
throw new MonosaccharideException("Error in setting stereocode: position out of range (" + position + ").");
}
stereoOut = stereoOut.substring(0, position - 1) + StereoConfiguration.Nonchiral.getStereosymbol() + stereoOut.substring(position - 1);
}
return(stereoOut);
}
/**
* Mark the nonchiral positions in a stereocode string.
* In contrast to "expandChiralonlyStereocode()" this method overwrites the stereochemistry of existing positions.
* It can be used to mark nonchiral positions in a residue like a-D-4-deoxy-Glcp (i.e. the basetype is a specific type or a trivial name)
* @param stereo StereoString to be processed, must cover the full monosaccharide (positions 1 to n)
* @param ms Monosaccharide, from which the information about nonchiral positions is received
* @return stereocode string with nonchiral positions marked
* @throws MonosaccharideException
*/
public static String markNonchiralPositionsInStereoString(String stereo, Monosaccharide ms) throws MonosaccharideException {
if(stereo.length() != ms.getSize()) {
throw new MonosaccharideException("Size mismatch error in markNonchiralPositions: " + stereo + "/" + ms.getSize());
} else {
ArrayList<Integer> stereoLossPos = ms.getStereolossPositions();
char[] stereoChars = stereo.toCharArray();
for(int i = 0; i < stereoLossPos.size(); i++) {
int position = stereoLossPos.get(i);
if(position == 0) { //*** unknown position ***
System.out.println("Warning: skipped unknown stereoloss position (markNonchiralPositions).");
continue;
}
if(position < 0 || position > ms.getSize()) {
throw new MonosaccharideException("Error in markNonchiralPositions: position out of range: " + position);
}
stereoChars[position - 1] = StereoConfiguration.Nonchiral.getStereosymbol();
}
stereo = String.valueOf(stereoChars);
}
return(stereo);
}
/**
* Generate a stereocode string for a superclass residue
* (i.e. a stereocode string that consists of unknown positions only)
* @param size the size of the residue
* @return the stereo string, e.g. for a hexose "0xxxx0";
*/
public static String getSuperclassStereostring(int size) {
String outStr = "";
if(size > 0) {
outStr += Stereocode.StereoN;
}
for(int i = 0; i < size - 2; i++) {
outStr += Stereocode.StereoX;
}
if(size > 1) {
outStr += Stereocode.StereoN;
}
return outStr;
}
/**
* Returns an ArrayList containing the configurations represented by this stereocode.
* Each element of the List represents the stereochemistry of one single monosaccharide backbone atom
* @return ArrayList of configurations
* @throws ResourcesDbException
*/
public ArrayList<StereoConfiguration> toConfigurationList() throws ResourcesDbException {
ArrayList<StereoConfiguration> configList = new ArrayList<StereoConfiguration>();
for(int i = 0; i < getStereoStr().length(); i++) {
//try {
configList.add(StereoConfiguration.forStereosymbol(getStereoStr().charAt(i)));
//} catch(MonosaccharideException me) { //*** stereoString contains illegal symbols ***
// System.err.println("Cannot assign configuration to stereocode symbol (" + getStereoStr().substring(i, i + 1) + ")");
// configList.add(StereoConfiguration.Unknown);
//}
}
return(configList);
}
/**
* Set a single position in a stereocode string.
* @param stereo: The stereocode string to be altered.
* @param posStr: The configuration symbol to be assigned to the given position (must be a valid configuration symbol of size 1).
* @param pos: The position at which the configuration symbol is set.
* @return The altered stereocode string.
* @throws ResourcesDbException in case "pos" is not a position covered by the stereocode string or "posStr" is not a valid configuration symbol.
*/
public static String setPositionInStereoString(String stereo, char posChar, int pos) throws ResourcesDbException {
if(pos <= 0 || pos > stereo.length()) {
throw new MonosaccharideException("Stereocode.setPosition: position out of range (" + (pos + 1) + ")");
}
if(StereoConfiguration.forStereosymbol(posChar) == null) {
throw new MonosaccharideException("Stereocode.setPosition: Symbol to be set is not a valid configuration symbol: " + posChar);
}
if(pos < stereo.length()) {
stereo = stereo.substring(0, pos - 1) + posChar + stereo.substring(pos);
} else {
stereo = stereo.substring(0, pos - 1) + posChar;
}
return(stereo);
}
public static String setPositionInStereoString(String stereo, StereoConfiguration posConf, int pos) throws ResourcesDbException {
return Stereocode.setPositionInStereoString(stereo, posConf.getStereosymbol(), pos);
}
public static StereoConfiguration getPositionFromStereoString(String stereo, int pos) throws ResourcesDbException {
if(pos < 1 || pos > stereo.length()) {
throw new MonosaccharideException("position out of range: " + pos);
}
return(StereoConfiguration.forStereosymbol(stereo.charAt(pos - 1)));
}
public StereoConfiguration getPositionConfiguration(int pos) throws ResourcesDbException {
return getPositionFromStereoString(this.getStereoStr(), pos);
}
public static ArrayList<String> getBasetypelistFromStereocode(Monosaccharide ms, BasetypeTemplateContainer container) throws ResourcesDbException {
return(getBasetypelistFromStereoString(ms.getStereoStr(), ms, container));
}
public static ArrayList<String> getBasetypelistFromStereoString(String stereo, Monosaccharide ms, BasetypeTemplateContainer container) throws ResourcesDbException {
if(ms.getRingStart() > 1) { //*** anomeric center not at position1 => mask potential anomeric stereochemistry ***
stereo = Stereocode.setPositionInStereoString(stereo, StereoConfiguration.Nonchiral.getStereosymbol(), ms.getRingStart());
}
stereo = stereo.substring(1); //*** remove position1 (always nonchiral or anomeric) ***
stereo = stereo.replaceAll("" + StereoConfiguration.Nonchiral.getStereosymbol(), "");
ArrayList<String> basetypeList = new ArrayList<String>();
if(!stereo.replaceAll("" + StereoConfiguration.Unknown.getStereosymbol(), "").equals("")) { //*** residue is not just a superclass ***
if(stereo.indexOf(StereoConfiguration.Unknown.getStereosymbol()) != -1) {
throw new MonosaccharideException("Stereocode string contains unknown positions.");
}
String basetypeStr;
while(stereo.length() > 0) {
if(stereo.length() > 4) {
basetypeStr = container.getBasetypeTemplateByStereoString(stereo.substring(0, 4)).getBaseName();
basetypeStr = Stereocode.getConfigurationFromStereoString(stereo.substring(0, 4)).getSymbol() + "-" + basetypeStr;
stereo = stereo.substring(4);
} else {
basetypeStr = container.getBasetypeTemplateByStereoString(stereo).getBaseName();
basetypeStr = Stereocode.getConfigurationFromStereoString(stereo).getSymbol() + "-" + basetypeStr;
stereo = "";
}
basetypeList.add(0, basetypeStr);
}
}
return(basetypeList);
}
public static ArrayList<String> prepareStereocodeForBasetypeDetermination(Monosaccharide ms) throws ResourcesDbException {
ArrayList<String> stereoList = new ArrayList<String>();
String stereo = ms.getStereoStr();
if(ms.getRingStart() > 1) { //*** anomeric center not at position1 => mask potential anomeric stereochemistry ***
stereo = Stereocode.setPositionInStereoString(stereo, StereoConfiguration.Nonchiral.getStereosymbol(), ms.getRingStart());
}
stereo = stereo.substring(1); //*** remove position1 (always nonchiral or anomeric) ***
stereo = stereo.replaceAll("" + StereoConfiguration.Nonchiral.getStereosymbol(), ""); //*** remove nonchiral positions ***
if(!stereo.replaceAll("" + StereoConfiguration.Unknown.getStereosymbol(), "").equals("")) { //*** residue is not just a superclass ***
while(stereo.length() > 0) {
if(stereo.length() > 4) {
stereoList.add(0, stereo.substring(0, 4));
stereo = stereo.substring(4);
} else {
stereoList.add(0, stereo);
stereo = "";
}
}
}
return stereoList;
}
/**
* Check, if this stereocode contains an uncertain position
* @return true, if a position other than D, L or non-chiral is found
*/
public boolean hasUncertainPosition() {
return Stereocode.stereoStringHasUncertainPosition(this.getStereoStr());
}
/**
* Check, if a stereo String has an uncertain position
* @param stereo the stereo String to check
* @return true, if a position other than D, L or non-chiral is found
*/
public static boolean stereoStringHasUncertainPosition(String stereo) {
if(!stereo.matches("^[" + Stereocode.StereoD + Stereocode.StereoL + Stereocode.StereoN + "]*$")) {
return true;
}
return false;
}
//*****************************************************************************
//*** other methods: **********************************************************
//*****************************************************************************
public String toString() {
return(this.stereoStr);
}
public Stereocode clone() {
return new Stereocode(this.getStereoStr());
}
}