/*
* 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.io;
import java.util.ArrayList;
import org.eurocarbdb.resourcesdb.*;
import org.eurocarbdb.resourcesdb.glycoconjugate_derived.LinkageType;
import org.eurocarbdb.resourcesdb.monosaccharide.*;
import org.eurocarbdb.resourcesdb.template.TrivialnameTemplate;
import org.eurocarbdb.resourcesdb.template.SubstituentTemplate;
import org.eurocarbdb.resourcesdb.template.BasetypeTemplate;
import org.eurocarbdb.resourcesdb.template.TemplateContainer;
import org.eurocarbdb.resourcesdb.util.NumberPrefix;
import org.eurocarbdb.resourcesdb.util.StringUtils;
import org.eurocarbdb.resourcesdb.util.Utils;
public class BcsdbExporter extends StandardExporter implements MonosaccharideExporter {
private String configStr = null;
private String basetypeStr = null;
//*****************************************************************************
//*** constructors: ***********************************************************
//*****************************************************************************
public BcsdbExporter() {
this(null, null);
}
public BcsdbExporter(Config conf) {
this(conf, null);
}
public BcsdbExporter(Config conf, TemplateContainer container) {
super(GlycanNamescheme.BCSDB, conf, container);
}
//*****************************************************************************
//*** export methods: *********************************************************
//*****************************************************************************
/**
* Generate the name string of a monosaccharide.
* If a trivial name exists that will be used only if it is the primary alias for the monosaccharide.
* @param ms the monosaccharide the name of which is generated
* @return the name string
* @throws ResourcesDbException
*/
public String export(Monosaccharide ms) throws ResourcesDbException {
return export(ms, this.getConfig().isForceTrivialNames());
}
/**
* Generate the name string of a monosaccharide.
* If forceTrivial is set to true and a trivial name exists that will be used regardless if the trivial name is the primary alias or not,
* while forceTrivial set to false will return a trivial name only if it is the primary alias.
* @param ms the monosaccharide the name of which is generated
* @param forceTrivial a flag to indicate if a potential trivial name shall be used even if that is a secondary alias
* @return the name string
* @throws ResourcesDbException
*/
public String export(Monosaccharide ms, boolean forceTrivial) throws ResourcesDbException {
String outStr = "";
if(ms.getConfiguration() == null) {
String stereo = ms.getStereoStrWithoutAnomeric();
ms.setConfiguration(Stereocode.getConfigurationFromStereoString(stereo));
}
//*** check for trivialname: ***
TrivialnameTemplate trivTmpl = this.getTemplateContainer().getTrivialnameTemplateContainer().checkMsForTrivialname(GlycanNamescheme.BCSDB, ms);
this.setUsedTrivialnameTemplate(trivTmpl);
if(trivTmpl != null) {
if(trivTmpl.isDefaultConfigIsCompulsory()) {
this.configStr = "X";
} else {
this.configStr = String.valueOf(ms.getConfiguration().getBcsdbSymbol());
}
this.basetypeStr = trivTmpl.getPrimaryName(this.getNamescheme());
} else {
this.formatConfigAndBasetypeStrings(ms);
}
//*** write anomeric: ***
outStr += ms.getAnomer().getBcsdbSymbol();
//*** write config: ***
outStr += this.configStr;
//*** write anhydro modifications, if applicable: ***
ArrayList<CoreModification> anhydroList = ms.getCoreModifications(CoreModificationTemplate.ANHYDRO);
if(anhydroList != null && anhydroList.size() > 0) {
String anhydroStr = "";
int anhydroCount = 0;
for(CoreModification mod : anhydroList) {
if(this.trivialnameHasCoremod(mod)) {
continue;
}
if(anhydroCount > 0) {
anhydroStr += ",";
}
int pos1 = mod.getIntValuePosition1();
int pos2 = mod.getIntValuePosition2();
if(pos1 == 0) {
anhydroStr += "?";
} else {
anhydroStr += pos1;
}
anhydroStr += ",";
if(pos2 == 0) {
anhydroStr += "?";
} else {
anhydroStr += pos2;
}
anhydroStr += "anh";
anhydroCount ++;
}
if(anhydroCount > 0) {
outStr += anhydroStr;
}
}
//*** write deoxy modifications, if applicable: ***
ArrayList<CoreModification> deoxyList = ms.getCoreModifications(CoreModificationTemplate.DEOXY);
if(deoxyList != null && deoxyList.size() > 0) {
String deoxyStr = "";
int deoxyCount = 0;
for(CoreModification mod : deoxyList) {
if(this.trivialnameHasCoremod(mod)) {
continue;
}
if(deoxyCount > 0) {
deoxyStr += ",";
}
int pos = mod.getIntValuePosition1();
if(pos == 0) {
deoxyStr += "?";
} else {
deoxyStr += pos;
}
deoxyCount ++;
}
if(deoxyCount > 0) {
deoxyStr += "d";
outStr += deoxyStr;
}
}
//*** write basetype: ***
outStr += this.basetypeStr;
//*** write ring type: ***
if(ms.isAlditol()) {
outStr += Ringtype.UNKNOWN.getBcsdbSymbol();
} else {
outStr += ms.getRingtype().getBcsdbSymbol();
}
//*** write en modifications, if applicable: ***
ArrayList<CoreModification> enList = ms.getEnModifications();
if(enList != null && enList.size() > 0) {
String enString = "";
int enCount = 0;
for(CoreModification mod : enList) {
if(this.trivialnameHasCoremod(mod)) {
continue;
}
if(enCount > 0) {
enString += ",";
}
int pos = mod.getIntValuePosition1();
if(pos == 0) {
enString += "?";
} else {
enString += pos;
}
enCount ++;
}
if(enCount > 0) {
if(enCount == 1) {
enString += "en";
} else {
enString += NumberPrefix.forSize(enCount) + "en";
}
outStr += enString;
}
}
//*** write substitutions, if applicable: ***
outStr += this.formatSubstitutionsString(ms);
//*** write acid modification, if applicable: ***
if(ms.isUronic()) {
outStr += "A";
}
//*** write ulo / onic / aric modifications, if applicable: ***
ArrayList<CoreModification> uloList = ms.getCoreModifications(CoreModificationTemplate.KETO);
String uloString = "";
int uloCount = 0;
if(uloList != null && uloList.size() > 0) {
for(CoreModification mod : uloList) {
if(this.trivialnameHasCoremod(mod)) {
continue;
}
if(uloCount > 0) {
uloString += ",";
}
int pos = mod.getIntValuePosition1();
uloString += "-";
if(pos == 0) {
uloString += "?";
} else {
uloString += pos;
}
uloCount ++;
}
if(uloCount > 0) {
if(uloCount == 1 && uloString.equals("-2")) {
uloString = "";
}
uloString += "-";
if(uloCount > 1) {
uloString += NumberPrefix.forSize(uloCount);
}
uloString += "ulo";
outStr += uloString;
}
}
if(ms.isAldonic()) {
if(!this.trivialnameHasCoremod(ms.getCoreModification(CoreModificationTemplate.ACID, 1))) {
if(uloCount > 0) {
outStr += "sonic";
} else {
outStr += "-onic";
}
}
} else if(ms.isAldaric()) {
if(!this.trivialnameHasCoremod(ms.getCoreModification(CoreModificationTemplate.ACID, ms.getSize()))) {
if(uloCount > 0) {
outStr += "saric";
} else {
outStr += "-aric";
}
}
}
//*** write alditol modification, if applicable: ***
if(ms.isAlditol()) {
outStr += "-ol";
}
//*** return residue string: ***
return outStr;
}
private void formatConfigAndBasetypeStrings(Monosaccharide ms) throws ResourcesDbException {
ArrayList<String> stereoList = Stereocode.prepareStereocodeForBasetypeDetermination(ms);
this.configStr = "";
if(stereoList.size() == 0) { //*** residue is superclass ***
this.configStr += StereoConfiguration.Unknown.getBcsdbSymbol();
this.basetypeStr = StringUtils.camelCase(this.getTemplateContainer().getBasetypeTemplateContainer().getSuperclassTemplateBySize(ms.getSize()).getBaseName());
} else if(stereoList.size() == 1) { //*** residue has up to 4 stereocenters (excl. anomeric) ***
this.configStr += Stereocode.getConfigurationFromStereoString(stereoList.get(0)).getBcsdbSymbol();
BasetypeTemplate btTmpl = this.getTemplateContainer().getBasetypeTemplateContainer().getBasetypeTemplateByStereoString(stereoList.get(0));
String basename = btTmpl.getBaseName();
if(btTmpl.getSize() == ms.getSize()) {
if(basename.equalsIgnoreCase("tro")) {
basename = "thr";
}
this.basetypeStr = StringUtils.camelCase(basename);
} else {
if(basename.equalsIgnoreCase("tro")) {
basename = "thr";
}
this.basetypeStr = basename + StringUtils.camelCase(this.getTemplateContainer().getBasetypeTemplateContainer().getSuperclassTemplateBySize(ms.getSize()).getBaseName());
}
} else { //*** residue has more than 4 stereocenters (excl. anomeric) ***
this.configStr += StereoConfiguration.Nonchiral.getBcsdbSymbol();
this.basetypeStr = "";
for(String stereoFragment : stereoList) {
this.configStr += Stereocode.getConfigurationFromStereoString(stereoFragment).getBcsdbSymbol();
if(stereoFragment.length() > 1) {
BasetypeTemplate btTmpl = this.getTemplateContainer().getBasetypeTemplateContainer().getBasetypeTemplateByStereoString(stereoFragment);
this.basetypeStr += btTmpl.getBaseName();
}
}
this.basetypeStr += StringUtils.camelCase(this.getTemplateContainer().getBasetypeTemplateContainer().getSuperclassTemplateBySize(ms.getSize()).getBaseName());
}
}
private String formatSubstitutionsString(Monosaccharide ms) throws ResourcesDbException {
String substStr = "";
int substCount = 0;
for(Substitution subst : ms.getSubstitutions()) {
//*** format position(s): ***
String posStr;
posStr = Utils.formatPositionsString(subst.getPosition1(), "/", "?");
if(posStr.equals("2") && (subst.getTemplate().getName().equalsIgnoreCase(SubstituentTemplate.AMINOTEMPLATENAME) || subst.getTemplate().isExtendedAmine(this.getTemplateContainer().getSubstituentTemplateContainer())) && substCount == 0 && !subst.hasPosition2()) {
posStr = "";
}
if(subst.hasPosition2()) {
posStr += "," + Utils.formatPositionsString(subst.getPosition2(), "/", "?");
}
//*** format substituent name: ***
String substName = subst.getResidueIncludedName(GlycanNamescheme.BCSDB);
//*** consider special cases that occur with trivial names like Neu5Ac: ***
if(this.getUsedTrivialnameTemplate() != null) {
//*** check, if substitution is (fully or partly) included in trivial name: ***
int position1 = subst.getIntValuePosition1();
if(position1 > 0) {
Substitution trivSubst = this.getUsedTrivialnameTemplate().getSubstitutionByPosition(position1);
if(trivSubst != null) { //*** trivial name includes substitution at current position ***
if(trivSubst.equals(subst)) {
continue; //*** substitution is fully included in trivial name => must not repeated in substituents list ***
}
if(trivSubst.getName().equals(SubstituentTemplate.AMINOTEMPLATENAME)) { //*** substitution implied in trivial name is an amino group, check, what part of the substituent is to be added to the residue name: ***
if(subst.getResidueIncludedName(this.getNamescheme()) != null && this.getTemplateContainer().getSubstituentTemplateContainer().forName(this.getNamescheme(), subst.getResidueIncludedName(this.getNamescheme())).getName().equals(SubstituentTemplate.AMINOTEMPLATENAME)) {
continue; //*** most simple case: amine, which is already implied in trivial name, is residueIncludedName, and the rest of the substituent will be given as a separate residue ***
}
if(subst.getTemplate().isExtendedAmine(this.getTemplateContainer().getSubstituentTemplateContainer())) {
//*** trivial name includes amino group, substituent is N-linked => add name of corresponding o-linked substituent (without leading "O"), if possible: ***
String oLinkedEquivName = subst.getTemplate().getOLinkedEquivalent(this.getTemplateContainer().getSubstituentTemplateContainer());
if(oLinkedEquivName != null && oLinkedEquivName.length() > 0) {
//*** o-linked equivalent is defined, get template: ***
SubstituentTemplate oLinkedEquivTmpl = this.getTemplateContainer().getSubstituentTemplateContainer().forName(GlycanNamescheme.GLYCOCT, oLinkedEquivName);
String oLinkTmplSepDisp = oLinkedEquivTmpl.getSeparateDisplay(this.getNamescheme(), LinkageType.H_AT_OH);
String substTmplSepDisp = null; //subst.getTemplate().getSeparateDisplay(this.namescheme, LinkageType.H_AT_OH);
if(StringUtils.strCmpNullEqualsEmpty(oLinkTmplSepDisp, substTmplSepDisp)) {
oLinkedEquivName = oLinkedEquivTmpl.getPrimaryAlias(this.getNamescheme(), LinkageType.H_AT_OH).getResidueIncludedName();
substName = oLinkedEquivTmpl.getResidueIncludedName(this.getNamescheme(), LinkageType.H_AT_OH);
if(substName == null || substName.length() == 0) {
substName = oLinkedEquivTmpl.getSeparateDisplay(this.getNamescheme(), LinkageType.H_AT_OH);
}
//*** check, if leading "O" or "O-" is present in primary alias for the substitution,
//*** and if name without these letters is a secondary alias ***
//*** in that case, use the secondary alias: ***
if(oLinkedEquivName.startsWith("O")) {
oLinkedEquivName = oLinkedEquivName.substring(1);
}
if(oLinkedEquivName.startsWith("-")) {
oLinkedEquivName = oLinkedEquivName.substring(1);
}
if(oLinkedEquivTmpl.equals(this.getTemplateContainer().getSubstituentTemplateContainer().forName(this.getNamescheme(), oLinkedEquivName))) {
substName = oLinkedEquivName;
} else {
substName = subst.getResidueIncludedName(this.getNamescheme());
}
}
}
}
}
}
}
}
//*** add position(s) + substituent name to ms name string: ***
if(substName != null && substName.length() > 0) {
substStr += posStr + substName;
substCount++;
}
}
return substStr;
}
//*****************************************************************************
//*** other methods: **********************************************************
//*****************************************************************************
private boolean trivialnameHasCoremod(CoreModification mod) {
if(this.getUsedTrivialnameTemplate() != null) {
return this.getUsedTrivialnameTemplate().hasCoreModification(mod);
}
return false;
}
}