/*
* 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.glycoconjugate_derived;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import org.eurocarbdb.resourcesdb.glycoconjugate_derived.GlycoconjugateException;
import org.eurocarbdb.resourcesdb.glycoconjugate_derived.ComparatorModification;
/**
*
* @author rene
* TODO:
* - addModificaiton prüfen ob diese modifications hinzugefügt werden darf
*/
public class EcdbMonosaccharide
{
private EcdbAnomer m_enumAnomer;
private ArrayList<EcdbBaseType> m_aBaseType = new ArrayList<EcdbBaseType>();
private EcdbSuperclass m_enumSuperclass;
// both -1 for unknown ; both 0 vor open ring
public static final int UNKNOWN_RING = -1;
public static final int OPEN_CHAIN = 0;
private int m_iRingStart;
private int m_iRingEnd;
private ArrayList<EcdbModification> m_aModifications = new ArrayList<EcdbModification>();
public EcdbMonosaccharide(EcdbAnomer a_enumAnomer, EcdbSuperclass a_enumSuperclass) throws GlycoconjugateException
{
if ( a_enumAnomer == null )
{
throw new GlycoconjugateException("Anomer can't be null");
}
this.m_enumAnomer = a_enumAnomer;
if ( a_enumSuperclass == null )
{
throw new GlycoconjugateException("Superclass can't be null");
}
this.m_enumSuperclass = a_enumSuperclass;
this.m_iRingEnd = -1;
this.m_iRingStart = -1;
this.m_aModifications.clear();
this.m_aBaseType.clear();
}
public void setAnomer(EcdbAnomer a_enumAnomer) throws GlycoconjugateException
{
if ( a_enumAnomer == null )
{
throw new GlycoconjugateException("Anomer can't be null");
}
this.m_enumAnomer = a_enumAnomer;
}
public void setSuperclass( EcdbSuperclass a_enumSuperclass ) throws GlycoconjugateException
{
if ( a_enumSuperclass == null )
{
throw new GlycoconjugateException("Superclass can't be null");
}
this.m_enumSuperclass = a_enumSuperclass;
}
public EcdbSuperclass getSuperclass()
{
return this.m_enumSuperclass;
}
/**
*
* @return Anomer or null if not validated
*/
public EcdbAnomer getAnomer()
{
return this.m_enumAnomer;
}
/**
* -1 ; -1 for unknown
* 0 ; 0 for open chain
* @param a_iStart
* @param a_iEnd
* @return
* @throws GlycoconjugateException
*/
public void setRing(int a_iStart, int a_iEnd) throws GlycoconjugateException
{
if ( a_iStart > a_iEnd )
{
throw new GlycoconjugateException("Endpoint must be larger than startpoint");
}
if ( a_iStart < -1 )
{
throw new GlycoconjugateException("Startpoint must be equal or larger than -1");
}
this.m_iRingStart = a_iStart;
if ( a_iEnd < -1 )
{
throw new GlycoconjugateException("Endpoint must be equal or larger than -1");
}
this.m_iRingEnd = a_iEnd;
}
/**
*
* @return Positive Startposition of the ring or -1 if not validated
*/
public int getRingStart()
{
return this.m_iRingStart;
}
/**
*
* @return Positive endposition of the ring or -1 if not validated
*/
public int getRingEnd()
{
return this.m_iRingEnd;
}
public ArrayList<EcdbModification> getModificationList()
{
return this.m_aModifications;
}
public int getModificationCount()
{
return this.m_aModifications.size();
}
public EcdbModification getModification(int a_iModification) throws IndexOutOfBoundsException
{
return this.m_aModifications.get(a_iModification);
}
public void addModification( EcdbModification a_objModification ) throws GlycoconjugateException
{
if ( a_objModification == null )
{
throw new GlycoconjugateException("Modification can't be null");
}
this.m_aModifications.add(a_objModification);
}
public void removeModification( EcdbModification a_objModification )
{
this.m_aModifications.remove(a_objModification);
}
public ArrayList<EcdbBaseType> getBaseTypeList()
{
return this.m_aBaseType;
}
public int getBaseTypeCount()
{
return this.m_aBaseType.size();
}
public EcdbBaseType getBaseType(int a_iBaseType) throws IndexOutOfBoundsException
{
return this.m_aBaseType.get(a_iBaseType);
}
public void addBaseType( EcdbBaseType a_objBaseType ) throws GlycoconjugateException
{
if ( a_objBaseType == null )
{
throw new GlycoconjugateException("Basetype can't be null");
}
this.m_aBaseType.add(a_objBaseType);
}
public void setBaseType(ArrayList<EcdbBaseType> a_basetypeList) {
this.m_aBaseType = a_basetypeList;
}
public void removeBaseType( EcdbBaseType a_objBaseType)
{
this.m_aBaseType.remove(a_objBaseType);
}
public String getGlycoCTName()
{
String anomer=null;
String name=null;
String basetypes="";
String t_Modifications="";
String ringstart=null;
String ringend=null;
anomer=this.getAnomer().getSymbol();
for (Iterator<?> iter = this.getBaseTypeList().iterator(); iter.hasNext();) {
EcdbBaseType element = (EcdbBaseType) iter.next();
basetypes= basetypes+"-"+element.getName();
}
if (this.getRingStart()==-1){
ringstart="x";
}
else {
ringstart=String.valueOf(this.getRingStart());
}
if (this.getRingEnd()==-1){
ringend="x";
}
else {
ringend=String.valueOf(this.getRingEnd());
}
ComparatorModification cf =new ComparatorModification();
Collections.sort( this.m_aModifications , cf );
for (Iterator<?> iter = this.getModificationList().iterator(); iter.hasNext();) {
EcdbModification element = (EcdbModification) iter.next();
if (element.hasPositionTwo()){
t_Modifications=t_Modifications+
"|"+
element.getPositionOne()+
","+
element.getPositionTwo()+
":"+element.getName();
}
else {
t_Modifications=t_Modifications+
"|"+
element.getPositionOne()+
":"+element.getName();
}
}
//remove trailing ","
if (t_Modifications!="") t_Modifications=t_Modifications.substring(1,t_Modifications.length());
name= anomer+
basetypes +
"-"+
this.getSuperclass()+
"-"+
ringstart+
":"+
ringend;
if (t_Modifications!=""){
name+="|"+t_Modifications;
}
return name;
}
/**
* Test if the Monosaccharide is theoretically valid.
*
* Modification positions checked
* Modification coincidence checked
* Ring start and end: valid numbers including carbonyl group check
* Anomer settings: Open ring - anomer flag
* Superclass validated against stereochemical descriptor+modifications
*
* @return
* @throws GlycoconjugateException
*/
public boolean isValid() throws GlycoconjugateException
{
return true;
}
/**
* Calculates the stereocode
* @return
* @throws GlycoconjugateException
*/
public String getStereoCode() throws GlycoconjugateException
{
StringBuilder stereocode=null;
//validate monosaccharide before computing
if (this.isValid()!=true)
{
throw new GlycoconjugateException("Monosaccharide is invalid, cannot compute stereocode");
}
//Basetype == null -> Superclass definition
if (this.getBaseTypeCount()==0){
stereocode= new StringBuilder("*");
Integer count=this.getSuperclass().getNumberOfC();
for (int i = 0; i < count-1; i++) {
stereocode.append("*");
}
return stereocode.toString();
}
// If basetype is joker form "xgro" -> full stereocode is ***
for (Iterator<?> iter = this.getBaseTypeList().iterator(); iter.hasNext();) {
EcdbBaseType element = (EcdbBaseType) iter.next();
if (element.getStereo().contains("*")){
stereocode= new StringBuilder("*");
Integer count=this.getSuperclass().getNumberOfC();
for (int i = 0; i < count-1; i++) {
stereocode.append("*");
}
return stereocode.toString();
}
}
stereocode= new StringBuilder("0");
//normal case, defined sugar
for (Iterator<?> iter = this.getBaseTypeList().iterator(); iter.hasNext();) {
EcdbBaseType element = (EcdbBaseType) iter.next();
stereocode=stereocode.insert(1,element.getStereo());
}
// append trailing zero
stereocode.append("0");
//insert modifying zeros for stereolosses
/* conditions
*
* Terminal modifications do not alter stereocode
* If stereocode is already set to zero, do nothing
* Pure superclasses are excluded
*
*/
ComparatorModification cf =new ComparatorModification();
// Sort the modification list
Collections.sort( this.m_aModifications , cf );
// iterate over all modifications
for (Iterator<?> iter = this.getModificationList().iterator(); iter.hasNext();) {
EcdbModification element = (EcdbModification) iter.next();
// terminal does nothing -> ignore
if (this.getSuperclass().getNumberOfC()==element.getPositionOne() |
element.getPositionOne()==1) continue;
Boolean deoxyTrue = false;
if (element.hasPositionTwo()){
for (Iterator<?> iter2 = this.getModificationList().iterator(); iter2.hasNext();) {
EcdbModification element2 = (EcdbModification) iter2.next();
if ((element.getPositionOne()==element2.getPositionOne() &&
element2.getName()==EcdbModificationType.DEOXY.getName())||
(element.getPositionTwo()==element2.getPositionOne() &&
element2.getName()==EcdbModificationType.DEOXY.getName()))
{
deoxyTrue=true;
}
}
}
// bivalent modification
if (element.hasPositionTwo() && !deoxyTrue){
stereocode.insert(element.getPositionOne()-1,"1");
stereocode.insert(element.getPositionTwo()-1,"1");
}
//monovalent modification
else {
stereocode.insert(element.getPositionOne()-1,"1");
}
}
return stereocode.toString();
}
/**
* Calculates a bitfield of free OH-groups, "0" no OH, "1" existing OH
* @return
* @throws GlycoconjugateException
* @throws GlycoconjugateException
*/
public Integer getBitfield() throws GlycoconjugateException
{
return null;
}
public String getChemoCentricBitfield() throws GlycoconjugateException
{
return null;
}
/**
* Check if Modification exists in Monosaccharide
* @returns Boolean
* @throws GlycoconjugateException
* @see java.lang.Object#clone()
**/
public Boolean hasModification (EcdbModification a_objModification){
if (this.m_aModifications.contains(a_objModification)) {
return true;
}
else {
return false;
}
}
/**
* Check if Modification exists in Monosaccharide
* @returns Boolean
* @throws GlycoconjugateException
* @see java.lang.Object#clone()
**/
public Boolean hasModification(EcdbModificationType a_objModiType, Integer positionOne){
for (EcdbModification m: this.m_aModifications){
if (m.getName()==a_objModiType.getName() &&
m.getPositionOne()==positionOne ){
return true;
}
}
return false;
}
/**
* Check if Modification exists in Monosaccharide
* @returns Boolean
* @throws GlycoconjugateException
* @see java.lang.Object#clone()
**/
public Boolean hasModification(EcdbModificationType a_objModiType, Integer positionOne, Integer positionTwo){
for (EcdbModification m: this.m_aModifications){
if (m.getName()==a_objModiType.getName() &&
m.getPositionOne()==positionOne &&
m.getPositionTwo()==positionTwo){
return true;
}
}
return false;
}
public Boolean hasChild(Integer position, LinkageType linkageType){
// TODO: Implement check
return null;
}
/**
* Create a clone of the Monosaccharide. Doesn't clone the linkages.
* @throws GlycoconjugateException
* @see java.lang.Object#clone()
*/
@Override
public EcdbMonosaccharide clone()
{
EcdbMonosaccharide t_objMS = null;
try
{
// create new MS with Anomer and Superclass
t_objMS = new EcdbMonosaccharide( this.m_enumAnomer , this.m_enumSuperclass );
// ring
t_objMS.setRing( this.m_iRingStart , this.m_iRingEnd );
// basetype
for (Iterator<EcdbBaseType> t_iterBase = this.m_aBaseType.iterator(); t_iterBase.hasNext();)
{
t_objMS.addBaseType(t_iterBase.next());
}
// modification
for (Iterator<EcdbModification> t_iterModi = this.m_aModifications.iterator(); t_iterModi.hasNext();)
{
t_objMS.addModification(t_iterModi.next());
}
}
catch (GlycoconjugateException e)
{
}
return t_objMS;
}
public String toString() {
String outStr = "[";
outStr += "Anomer: " + this.getAnomer();
outStr += ", Basetype: " + this.getBaseTypeList();
outStr += ", Superclass: " + this.getSuperclass();
outStr += ", Ring: " + this.getRingStart() + ":" + this.getRingEnd();
outStr += ", Mod: " + this.getModificationList();
outStr += "]";
return outStr;
}
}