/* * 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.MolecularFramework.io.bcsdb; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import org.eurocarbdb.MolecularFramework.io.SugarImporterException; import org.eurocarbdb.MolecularFramework.io.SugarImporterText; import org.eurocarbdb.MolecularFramework.sugar.GlycoEdge; import org.eurocarbdb.MolecularFramework.sugar.GlycoGraph; import org.eurocarbdb.MolecularFramework.sugar.GlycoNode; import org.eurocarbdb.MolecularFramework.sugar.GlycoconjugateException; import org.eurocarbdb.MolecularFramework.sugar.Linkage; import org.eurocarbdb.MolecularFramework.sugar.Sugar; import org.eurocarbdb.MolecularFramework.sugar.SugarUnitRepeat; import org.eurocarbdb.MolecularFramework.sugar.UnvalidatedGlycoNode; import org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitorException; import org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitorReplaceName; /** * start ::= "-" [ "P" "-" ] <linkage_redu> ")" <rsugarchain> "(" <linkage_nonredu> "-" [ "P" "-" ] * | "P" "-" ")" [ <sidechain> ] <sugarchain> * | <sugarchain> * * rsugarchain ::= [ <sidechain> ] <residue> { <linkages> [ <sidechain> ] <residue> } <== spezielles zusatzkriterium ; * * sugarchain ::= <residue> { <linkage> [ <sidechain> ] <residue> } [ "(" <linkage_nonredu> "-" <residue> ] <== spezielles zusatzkriterium ; * * sidechain ::= "[" [ ":" ] <side_residue> [ <sidechain_follow> ] "]" * * side_residue ::= <residue> <linkage> | "P" "-" <linkage_redu> ")" | "S" "-" <linkage_redu> ")" * * sidechain_follow ::= "," <side_residue> [ <sidechain_follow> ] * | <sidechain> <residue> <linkage> [ <sidechain_follow> ] * | <residue> <linkage> [ <sidechain_follow> ] * | ":" <side_residue> [ <sidechain_follow> ] * * residue ::= <character> | '?' { <character> | <number> | '?' | '-' } * * linkage ::= "(" <linkage_nonredu> "-" { "P" "-" } <linkage_redu> ")" * * linkage_redu ::= "?" | <number> * * linkage_nonredu ::= "?" | <number> * * @author rene * */ public class SugarImporterBCSDB extends SugarImporterText { private int m_iMinRepeatCount = -1; private int m_iMaxRepeatCount = -1; private HashMap<SugarUnitRepeat,GlycoNode> m_hStartResiduum = new HashMap<SugarUnitRepeat,GlycoNode>(); /** * Parse a string according the gramatic of the language. Uses recursiv decent * * @param a_strStream String that is to parse * @throws ImportExeption */ public Sugar parse(String a_strStream) throws SugarImporterException { this.m_hStartResiduum.clear(); String[] t_aCodes = a_strStream.split(" // "); this.m_objSugar = new Sugar(); this.m_iPosition = -1; // Copie string and add endsymbol this.m_strText = t_aCodes[0].trim() + '$'; this.m_iLength = this.m_strText.length(); // get first token . Error ? ==> string empty this.nextToken(); this.start(); // sug definition if ( t_aCodes.length > 1 ) { t_aCodes = t_aCodes[1].split(";"); for (int t_iCounter = 0; t_iCounter < t_aCodes.length; t_iCounter++) { // comment field exists int t_iPos = t_aCodes[t_iCounter].indexOf("="); if ( t_iPos != -1 ) { String t_strSug = t_aCodes[t_iCounter].substring(0,t_iPos).trim(); if ( this.isReplaceString(t_strSug) ) { // found sugar residue GlycoVisitorReplaceName t_objVisitor = new GlycoVisitorReplaceName( t_strSug , t_aCodes[t_iCounter].substring(t_iPos+1).trim() ); try { t_objVisitor.start(this.m_objSugar); } catch (GlycoVisitorException e) { throw new SugarImporterException("BCSDB021", this.m_iPosition); } } } else { throw new SugarImporterException("BCSDB020", this.m_iPosition); } } } return this.m_objSugar; } /** * @param sug * @return */ private boolean isReplaceString(String a_strString) { if ( a_strString.equals("Sug") ) { return true; } if ( a_strString.equals("Subst") ) { return true; } if ( a_strString.equals("Subst1") ) { return true; } if ( a_strString.equals("Subst2") ) { return true; } if ( a_strString.equals("Subst3") ) { return true; } if ( a_strString.equals("Subst4") ) { return true; } if ( a_strString.equals("Subst5") ) { return true; } if ( a_strString.equals("PEN") ) { return true; } if ( a_strString.equals("HEX") ) { return true; } if ( a_strString.equals("HEP") ) { return true; } if ( a_strString.equals("DDHEP") ) { return true; } if ( a_strString.equals("LDHEP") ) { return true; } if ( a_strString.equals("OCT") ) { return true; } if ( a_strString.equals("NON") ) { return true; } if ( a_strString.equals("LIP") ) { return true; } if ( a_strString.equals("CER") ) { return true; } if ( a_strString.equals("ALK") ) { return true; } return false; } protected void start() throws SugarImporterException { try { this.startparsing(); } catch (GlycoconjugateException e) { throw new SugarImporterException("COMMON013", this.m_iPosition); } } /** * start ::= "-" [ "P" "-" ] <linkage_redu> ")" <rsugarchain> "(" <linkage_nonredu> "-" [ "P" "-" ] * | "P" "-" ")" [ <sidechain> ] <sugarchain> * | <sugarchain> * @throws GlycoconjugateException * @see de.glycosciences.glycoconjugate.io.SugarImporterText#start() */ protected void startparsing() throws SugarImporterException, GlycoconjugateException { if ( this.m_cToken == '-' ) { Linkage t_objInternalLinkage = null; SugarUnitRepeat t_objRepeat = new SugarUnitRepeat(); this.m_objSugar.addNode( t_objRepeat ); Linkage t_objLinkage = null; BcsdbSubTree t_objTree = null; t_objRepeat.setMinRepeatCount( this.m_iMinRepeatCount); t_objRepeat.setMaxRepeatCount(this.m_iMaxRepeatCount); // Repeatsugar // "-" { "P" "-" } <linkage_redu> ")" <rsugarchain> "(" <linkage_nonredu> "-" [ "P" "-" ] this.nextToken(); if ( (this.m_cToken == 'P' || this.m_cToken == 'S') && this.aheadToken(1) == '-' ) { UnvalidatedGlycoNode t_objResiduum = new UnvalidatedGlycoNode(); this.m_hStartResiduum.put(t_objRepeat,t_objResiduum); if ( this.m_cToken == 'S' ) { t_objResiduum.setName( "S" ); } else { t_objResiduum.setName( "P" ); } t_objRepeat.addNode(t_objResiduum); this.nextToken(); this.nextToken(); t_objInternalLinkage = new Linkage(); t_objInternalLinkage.addParentLinkage(1); t_objLinkage = new Linkage(); t_objLinkage.addChildLinkage(1); t_objTree = new BcsdbSubTree(); t_objTree.setGlycoNode(t_objResiduum); GlycoEdge t_objEdge = new GlycoEdge(); t_objEdge.addGlycosidicLinkage(t_objLinkage); t_objTree.setGlycoEdge(t_objEdge); } int t_iPos = this.linkage_redu(); if ( t_objInternalLinkage == null ) { t_objInternalLinkage = new Linkage(); t_objInternalLinkage.addParentLinkage(t_iPos); } else { t_objLinkage.addParentLinkage(t_iPos); } if ( this.m_cToken != ')' ) { throw new SugarImporterException("BCSDB001", this.m_iPosition); } this.nextToken(); GlycoNode t_objResidueChild = this.rsugarchain(t_objTree,t_objRepeat); if ( this.m_cToken != '(' ) { throw new SugarImporterException("BCSDB002", this.m_iPosition); } this.nextToken(); t_iPos = this.linkage_nonredu(); if ( this.m_cToken != '-' ) { throw new SugarImporterException("BCSDB003", this.m_iPosition); } this.nextToken(); if ( this.m_cToken == 'P' && this.aheadToken(1) == '-' ) { UnvalidatedGlycoNode t_objResiduum = new UnvalidatedGlycoNode(); t_objResiduum.setName( "P" ); t_objRepeat.addNode(t_objResiduum); this.nextToken(); this.nextToken(); Linkage t_objSubLinkage = new Linkage(); t_objSubLinkage.addParentLinkage(1); t_objSubLinkage.addChildLinkage(t_iPos); GlycoEdge t_objEdge = new GlycoEdge(); t_objEdge.addGlycosidicLinkage(t_objSubLinkage); t_objRepeat.addEdge(t_objResiduum,t_objResidueChild,t_objEdge); // finish internal repeat t_objInternalLinkage.addChildLinkage(1); t_objEdge = new GlycoEdge(); t_objEdge.addGlycosidicLinkage(t_objInternalLinkage); t_objRepeat.setRepeatLinkage(t_objEdge,this.m_hStartResiduum.get(t_objRepeat),t_objResiduum); } else { t_objInternalLinkage.addChildLinkage(t_iPos); GlycoEdge t_objEdge = new GlycoEdge(); t_objEdge.addGlycosidicLinkage(t_objInternalLinkage); t_objRepeat.setRepeatLinkage(t_objEdge,this.m_hStartResiduum.get(t_objRepeat),t_objResidueChild); } } else if ( (this.m_cToken == 'P' || this.m_cToken == 'S') && this.aheadToken(1) == '-' ) { // "P" "-" ")" [ <sidechain> ] <sugarchain> UnvalidatedGlycoNode t_objResiduum = new UnvalidatedGlycoNode(); if ( this.m_cToken == 'S' ) { t_objResiduum.setName( "S" ); } else { t_objResiduum.setName( "P" ); } this.nextToken(); this.nextToken(); int t_iLink = this.linkage_redu(); if ( this.m_cToken != ')' ) { throw new SugarImporterException("BCSDB007", this.m_iPosition); } this.nextToken(); // subtrees speichern ArrayList<BcsdbSubTree> t_aSubtree= new ArrayList<BcsdbSubTree>(); GlycoEdge t_objEdge = new GlycoEdge(); Linkage t_objLinkage = new Linkage(); t_objLinkage.addChildLinkage(1); t_objLinkage.addParentLinkage(t_iLink); t_objEdge.addGlycosidicLinkage(t_objLinkage); // add residue this.m_objSugar.addNode(t_objResiduum); BcsdbSubTree t_objTree = new BcsdbSubTree(); t_objTree.setGlycoEdge(t_objEdge); t_objTree.setGlycoNode(t_objResiduum); t_aSubtree.add(t_objTree); if ( this.m_cToken == '[' ) { // parse sidechain this.sidechain(t_aSubtree,this.m_objSugar); } this.sugarchain( t_aSubtree , this.m_objSugar); } else { // Nonrepeatsugar // <sugarchain> this.sugarchain( new ArrayList<BcsdbSubTree>() , this.m_objSugar ); } if ( ! this.finished() ) { throw new SugarImporterException("BCSDB004", this.m_iPosition); } } /** * rsugarchain ::= [ <sidecharin> ] <residue> { <linkages> [ "[" <sidechain> "]" ] <residue> } <== spezielles zusatzkriterium ; * * @param a_objSubLinkage sublinkage, can be null * @return letztes Residuem * @throws GlycoconjugateException */ private GlycoNode rsugarchain(BcsdbSubTree a_objSubTree,SugarUnitRepeat a_objRepeat) throws SugarImporterException, GlycoconjugateException { GlycoNode t_objResiduum; BcsdbSubTree t_objSubTree; ArrayList<BcsdbSubTree> t_aSubtrees = new ArrayList<BcsdbSubTree>(); if ( a_objSubTree != null ) { t_aSubtrees.add(a_objSubTree); } if ( this.m_cToken == '[' ) { this.sidechain(t_aSubtrees,a_objRepeat); } int t_iStartPosition = this.m_iPosition; UnvalidatedGlycoNode t_objResiduumUn = new UnvalidatedGlycoNode(); // save Residuename in Monosaccharid Object this.residue(); t_objResiduumUn.setName( this.m_strText.substring( t_iStartPosition , this.m_iPosition ) ); t_objResiduum = t_objResiduumUn; if ( !this.m_hStartResiduum.containsKey(a_objRepeat) ) { this.m_hStartResiduum.put(a_objRepeat,t_objResiduum); } a_objRepeat.addNode(t_objResiduum); // add subresidues for (Iterator<BcsdbSubTree> t_iterSub = t_aSubtrees.iterator(); t_iterSub.hasNext();) { t_objSubTree = t_iterSub.next(); a_objRepeat.addEdge(t_objResiduum,t_objSubTree.getGlycoNode(),t_objSubTree.getGlycoEdge()); } while ( this.m_cToken == '(' && this.m_strText.indexOf(')',this.m_iPosition) != -1 ) { // there is one or more residues left to parse t_aSubtrees = new ArrayList<BcsdbSubTree>(); // parse t_objSubTree = this.linkage(t_objResiduum,a_objRepeat); t_aSubtrees.add(t_objSubTree); if ( this.m_cToken == '[' ) { this.sidechain(t_aSubtrees,a_objRepeat); } t_iStartPosition = this.m_iPosition; this.residue(); t_objResiduumUn = new UnvalidatedGlycoNode(); t_objResiduumUn.setName( this.m_strText.substring( t_iStartPosition , this.m_iPosition ) ); a_objRepeat.addNode(t_objResiduumUn); t_objResiduum = t_objResiduumUn; // add subresidues for (Iterator<BcsdbSubTree> t_iterSub = t_aSubtrees.iterator(); t_iterSub.hasNext();) { t_objSubTree = t_iterSub.next(); a_objRepeat.addEdge(t_objResiduum,t_objSubTree.getGlycoNode(),t_objSubTree.getGlycoEdge()); } } return t_objResiduum; } /** * sugarchain ::= <residue> { <linkage> [ <sidechain> ] <residue> } [ "(" <linkage_nonredu> "-" <residue> ] <== spezielles zusatzkriterium ; * @param a_aSubLinkages All linkages "below" this residue * @throws GlycoconjugateException */ private void sugarchain(ArrayList<BcsdbSubTree> a_aSubLinkages,GlycoGraph a_objSugar) throws SugarImporterException, GlycoconjugateException { int t_iStartPosition = this.m_iPosition; UnvalidatedGlycoNode t_objResiduum1; UnvalidatedGlycoNode t_objResiduum2; ArrayList<BcsdbSubTree> t_aLinkages; // save Residuename in Monosaccharid Object this.residue(); t_objResiduum1 = new UnvalidatedGlycoNode(); t_objResiduum1.setName( this.m_strText.substring( t_iStartPosition , this.m_iPosition ) ); a_objSugar.addNode(t_objResiduum1); // attache all sublinkages for (Iterator<BcsdbSubTree> t_iterLinkages = a_aSubLinkages.iterator(); t_iterLinkages.hasNext();) { BcsdbSubTree t_objSubLinake = t_iterLinkages.next(); a_objSugar.addEdge(t_objResiduum1,t_objSubLinake.getGlycoNode(),t_objSubLinake.getGlycoEdge()); } // { <linkage> [ <sidechain> ] <residue> } [ "(" <linkage_nonredu> "-" <residue> ] <== spezielles zusatzkriterium ; while ( this.m_cToken == '(' && this.m_strText.indexOf(')',this.m_iPosition) != -1 ) { t_aLinkages = new ArrayList<BcsdbSubTree>(); // <linkage> [ <sidechain> ] <residue> BcsdbSubTree t_objSubLinkage = this.linkage(t_objResiduum1,a_objSugar); t_aLinkages.add(t_objSubLinkage); if ( this.m_cToken == '[' ) { this.sidechain( t_aLinkages , a_objSugar ); } // parse residue t_iStartPosition = this.m_iPosition; this.residue(); t_objResiduum2 = new UnvalidatedGlycoNode(); t_objResiduum2.setName( this.m_strText.substring( t_iStartPosition , this.m_iPosition ) ); a_objSugar.addNode(t_objResiduum2); // attache childs from the subchain for (Iterator<BcsdbSubTree> t_iterSub = t_aLinkages.iterator(); t_iterSub.hasNext();) { BcsdbSubTree t_objSub = t_iterSub.next(); a_objSugar.addEdge(t_objResiduum2,t_objSub.getGlycoNode(),t_objSub.getGlycoEdge()); } t_objResiduum1 = t_objResiduum2; } // [ "(" <linkage_nonredu> "-" <residue> ] if ( this.m_cToken == '(' ) { this.nextToken(); int t_iPosition = this.linkage_nonredu(); if ( this.m_cToken != '-' ) { throw new SugarImporterException("BCSDB006", this.m_iPosition); } while ( this.m_cToken == '-' ) { this.nextToken(); t_iStartPosition = this.m_iPosition; this.residue(); t_objResiduum2 = new UnvalidatedGlycoNode(); t_objResiduum2.setName( this.m_strText.substring( t_iStartPosition , this.m_iPosition ) ); a_objSugar.addNode(t_objResiduum2); // create Linkage Linkage t_objEndLinkage = new Linkage(); t_objEndLinkage.addChildLinkage(t_iPosition); t_objEndLinkage.addParentLinkage(1); GlycoEdge t_objEndEdge = new GlycoEdge(); t_objEndEdge.addGlycosidicLinkage(t_objEndLinkage); a_objSugar.addEdge(t_objResiduum2,t_objResiduum1,t_objEndEdge); t_objResiduum1 = t_objResiduum2; } } } /** * linkage ::= "(" <linkage_nonredu> "-" { "P" "-" } <linkage_redu> ")" * * Bastelt das übergebene Residue in die Linkage ein und gibt diese dann zurück. Residuem wird NICHT in den Zucker eingefügt. * * @throws SugarImporterException * @throws GlycoconjugateException */ private BcsdbSubTree linkage(GlycoNode a_objChild, GlycoGraph a_objSugar) throws SugarImporterException, GlycoconjugateException { Linkage t_objLinkage = new Linkage(); GlycoEdge t_objEdge = new GlycoEdge(); GlycoNode t_objChildResidue = a_objChild; if ( this.m_cToken != '(' ) { throw new SugarImporterException("BCSDB005", this.m_iPosition); } this.nextToken(); int t_iPosi = this.linkage_nonredu(); // fill data in t_objLinkage.addChildLinkage(t_iPosi); if ( this.m_cToken != '-' ) { throw new SugarImporterException("BCSDB006", this.m_iPosition); } this.nextToken(); while ( this.m_cToken == 'P' && this.aheadToken(1) == '-') { UnvalidatedGlycoNode t_objResiduum = new UnvalidatedGlycoNode(); t_objResiduum.setName( "P" ); a_objSugar.addNode(t_objResiduum); t_objLinkage.addParentLinkage(1); t_objEdge.addGlycosidicLinkage(t_objLinkage); a_objSugar.addEdge(t_objResiduum,t_objChildResidue,t_objEdge); // create new Linkage t_objLinkage = new Linkage(); t_objEdge = new GlycoEdge(); t_objLinkage.addChildLinkage(1); t_objChildResidue = t_objResiduum; this.nextToken(); if (this.m_cToken != '-' ) { throw new SugarImporterException("BCSDB010", this.m_iPosition); } this.nextToken(); } t_iPosi = this.linkage_redu(); t_objLinkage.addParentLinkage(t_iPosi); if ( this.m_cToken != ')' ) { throw new SugarImporterException("BCSDB007", this.m_iPosition); } this.nextToken(); BcsdbSubTree t_objSubTree = new BcsdbSubTree(); t_objSubTree.setGlycoNode(t_objChildResidue); t_objEdge.addGlycosidicLinkage(t_objLinkage); t_objSubTree.setGlycoEdge(t_objEdge); return t_objSubTree; } /** * @throws SugarImporterException * */ private int linkage_nonredu() throws SugarImporterException { if ( this.m_cToken == '?' ) { this.nextToken(); return Linkage.UNKNOWN_POSITION; } else { return this.number(); } } /** * linkage_redu ::= "?" | <number> * @throws SugarImporterException */ private int linkage_redu() throws SugarImporterException { if ( this.m_cToken == '?' ) { this.nextToken(); return Linkage.UNKNOWN_POSITION; } else { return this.number(); } } /** * residue ::= <character> | '?' { <character> | <number> | '?' | ',' | '|' | '-' | '@' | '{' | '}' |'=' } * @throws SugarImporterException */ private void residue() throws SugarImporterException { int t_iDigit = (int) this.m_cToken;; if ( this.m_cToken == '?' ) { this.nextToken(); } else if ( t_iDigit > 47 && t_iDigit < 58 ) { this.number(); } else { this.character(); } while ( this.m_cToken != '$' && this.m_cToken != '(' && this.m_cToken != ']' ) { t_iDigit = (int) this.m_cToken; if ( t_iDigit > 47 && t_iDigit < 58 ) { this.number(); } else if ( this.m_cToken == '?' ) { this.nextToken(); } else if ( this.m_cToken == '|' ) { this.nextToken(); } else if ( this.m_cToken == ',' ) { this.nextToken(); } else if ( this.m_cToken == '-') { this.nextToken(); } else if ( this.m_cToken == '@') { this.nextToken(); } else if ( this.m_cToken == '=') { this.nextToken(); } else if ( this.m_cToken == '{') { this.nextToken(); } else if ( this.m_cToken == '}') { this.nextToken(); } else { this.character(); } } } /** * muss was global ablegen um multi-valent residues zu vervollständigen * * sidechain ::= "[" [ ":" ] <side_residue> [ <sidechain_follow> ] "]" * * @param a_aSubTrees * * @throws GlycoconjugateException */ private void sidechain(ArrayList<BcsdbSubTree> a_aSubTrees,GlycoGraph a_objSugar) throws SugarImporterException, GlycoconjugateException { BcsdbSubTree t_objSubTree = null; boolean t_bMultilinked = false; if ( this.m_cToken != '[' ) { throw new SugarImporterException("BCSDB009", this.m_iPosition); } this.nextToken(); if ( this.m_cToken == ':' ) { this.nextToken(); t_bMultilinked = true; } // wenn multi = true dann wird das residue nicht im zucker gesetzt t_objSubTree = this.side_residue(t_bMultilinked,a_objSugar); if ( t_bMultilinked ) { if ( this.m_cToken != ']' && this.m_cToken != ',' && this.m_cToken != ':' ) { throw new SugarImporterException("BCSDB015", this.m_iPosition); } // multiresidue einhängen int t_iPosition = a_aSubTrees.size() - 1; if ( t_iPosition < 0 ) { throw new SugarImporterException("BCSDB016", this.m_iPosition); } BcsdbSubTree t_objOrginal = a_aSubTrees.get( t_iPosition ); if ( t_objOrginal.getGlycoNode().getClass() != UnvalidatedGlycoNode.class || t_objSubTree.getGlycoNode().getClass() != UnvalidatedGlycoNode.class ) { throw new SugarImporterException("BCSDB017", this.m_iPosition); } UnvalidatedGlycoNode t_objChildOne = (UnvalidatedGlycoNode)t_objOrginal.getGlycoNode(); UnvalidatedGlycoNode t_objChildTwo = (UnvalidatedGlycoNode)t_objSubTree.getGlycoNode(); if ( !t_objChildOne.getName().equals( t_objChildTwo.getName() ) ) { throw new SugarImporterException("BCSDB011", this.m_iPosition); } GlycoEdge t_objEdge = t_objOrginal.getGlycoEdge(); for (Iterator<Linkage> t_iterLinkages = t_objSubTree.getGlycoEdge().getGlycosidicLinkages().iterator(); t_iterLinkages.hasNext();) { t_objEdge.addGlycosidicLinkage(t_iterLinkages.next()); } t_objSubTree = null; } if( this.m_cToken != ']' ) { this.sidechain_follow(a_aSubTrees,t_objSubTree,a_objSugar); } else { if ( t_objSubTree != null ) { a_aSubTrees.add(t_objSubTree); } } if ( this.m_cToken != ']' ) { throw new SugarImporterException("BCSDB008", this.m_iPosition); } this.nextToken(); } /** * * wenn multi = true dann wird das residue nicht im zucker gesetzt * * side_residue ::= <residue> <linkage> | "P" "-" <linkage_redu> ")" | "S" "-" <linkage_redu> ")" * * @throws SugarImporterException * @throws GlycoconjugateException * */ private BcsdbSubTree side_residue(boolean a_bMultilinked,GlycoGraph a_objSugar) throws SugarImporterException, GlycoconjugateException { Linkage t_objLinkage; GlycoEdge t_objEdge; int t_iPos; if ( ( this.m_cToken == 'P' || this.m_cToken == 'S' ) && this.aheadToken(1) == '-' ) { // "P" "-" <linkage_redu> ")" int t_iResidueCounter = 0; UnvalidatedGlycoNode t_objResiduum = new UnvalidatedGlycoNode(); if ( this.m_cToken == 'P' ) { t_objResiduum.setName( "P" ); } else { t_objResiduum.setName( "S" ); } t_iResidueCounter++; this.nextToken(); this.nextToken(); if ( !a_bMultilinked ) { a_objSugar.addNode(t_objResiduum); } while( ( this.m_cToken == 'P' || this.m_cToken == 'S' ) && this.aheadToken(1) == '-' ) { UnvalidatedGlycoNode t_objRes2 = new UnvalidatedGlycoNode(); if ( this.m_cToken == 'P' ) { t_objRes2.setName( "P" ); } else { t_objRes2.setName( "S" ); } this.nextToken(); this.nextToken(); a_objSugar.addNode(t_objRes2); // Edge t_objEdge = new GlycoEdge(); t_objLinkage = new Linkage(); t_objLinkage.addChildLinkage(1); t_objLinkage.addParentLinkage(1); t_objEdge.addGlycosidicLinkage(t_objLinkage); a_objSugar.addEdge(t_objRes2,t_objResiduum,t_objEdge); t_objResiduum = t_objRes2; t_iResidueCounter++; } if ( a_bMultilinked && t_iResidueCounter > 1 ) { throw new SugarImporterException("BCSDB015", this.m_iPosition); } t_iPos = this.linkage_redu(); // Edge t_objEdge = new GlycoEdge(); t_objLinkage = new Linkage(); t_objLinkage.addChildLinkage(1); t_objLinkage.addParentLinkage(t_iPos); t_objEdge.addGlycosidicLinkage(t_objLinkage); if ( this.m_cToken != ')' ) { throw new SugarImporterException("BCSDB007", this.m_iPosition); } this.nextToken(); BcsdbSubTree t_objSubTree = new BcsdbSubTree(); t_objSubTree.setGlycoEdge(t_objEdge); t_objSubTree.setGlycoNode(t_objResiduum); return t_objSubTree; } else { // <residue> <linkage> int t_iStartPosition = this.m_iPosition; this.residue(); UnvalidatedGlycoNode t_objResiduum = new UnvalidatedGlycoNode(); t_objResiduum.setName( this.m_strText.substring( t_iStartPosition , this.m_iPosition ) ); if ( !a_bMultilinked ) { a_objSugar.addNode(t_objResiduum); } return this.linkage(t_objResiduum,a_objSugar); } } /** * sidechain_follow ::= "," <side_residue> [ <sidechain_follow> ] * | <sidechain> <residue> <linkage> [ <sidechain_follow> ] * | <residue> <linkage> [ <sidechain_follow> ] * | ":" <side_residue> [ <sidechain_follow> ] * @param a_objLastLinkage * @param a_aSubLinkages * @throws SugarImporterException * @throws GlycoconjugateException */ private void sidechain_follow(ArrayList<BcsdbSubTree> a_aSubLinkages, BcsdbSubTree a_objLastLinkage, GlycoGraph a_objSugar) throws SugarImporterException, GlycoconjugateException { BcsdbSubTree t_objSubtree = null; int t_iStartPosition = 0; if ( this.m_cToken == ',' ) { // new Branch // "," <side_residue> [ <sidechain_follow> ] // add old Linkage to the SubLinkage array if ( a_objLastLinkage != null ) { a_aSubLinkages.add(a_objLastLinkage); } // parsing new branch this.nextToken(); t_objSubtree = this.side_residue(false,a_objSugar); if ( this.m_cToken != ']' ) { this.sidechain_follow(a_aSubLinkages,t_objSubtree,a_objSugar); } else { a_aSubLinkages.add(t_objSubtree); } } else if ( this.m_cToken == '[' ) { // additional level of sidechain if ( a_objLastLinkage == null ) { throw new SugarImporterException("BCSDB014", this.m_iPosition); } // <sidechain> <residue> <linkage> [ <sidechain_follow> ] ArrayList<BcsdbSubTree> t_aSubLinkages = new ArrayList<BcsdbSubTree>(); t_aSubLinkages.add(a_objLastLinkage); this.sidechain(t_aSubLinkages,a_objSugar); t_iStartPosition = this.m_iPosition; this.residue(); UnvalidatedGlycoNode t_objResiduum = new UnvalidatedGlycoNode(); t_objResiduum.setName( this.m_strText.substring( t_iStartPosition , this.m_iPosition ) ); a_objSugar.addNode(t_objResiduum); // attach all subresidues for (Iterator<BcsdbSubTree> t_iterSub = t_aSubLinkages.iterator(); t_iterSub.hasNext();) { BcsdbSubTree t_objSub = t_iterSub.next(); a_objSugar.addEdge(t_objResiduum,t_objSub.getGlycoNode(),t_objSub.getGlycoEdge()); } t_objSubtree = this.linkage(t_objResiduum,a_objSugar); if ( this.m_cToken != ']' ) { this.sidechain_follow(a_aSubLinkages,t_objSubtree,a_objSugar); } else { a_aSubLinkages.add(t_objSubtree); } } else if ( this.m_cToken == ':' ) { // multi linked residue if ( a_objLastLinkage == null ) { throw new SugarImporterException("BCSDB013", this.m_iPosition); } a_aSubLinkages.add(a_objLastLinkage); // ":" <side_residue> [ <sidechain_follow> ] this.nextToken(); t_objSubtree = this.side_residue(true,a_objSugar); if ( this.m_cToken != ']' && this.m_cToken != ',' && this.m_cToken != ':' ) { throw new SugarImporterException("BCSDB015", this.m_iPosition); } // multiresidue einhaengen int t_iPosition = a_aSubLinkages.size() - 1; if ( t_iPosition < 0 ) { throw new SugarImporterException("BCSDB016", this.m_iPosition); } BcsdbSubTree t_objOrginal = a_aSubLinkages.get( t_iPosition ); if ( t_objOrginal.getGlycoNode().getClass() != UnvalidatedGlycoNode.class || t_objSubtree.getGlycoNode().getClass() != UnvalidatedGlycoNode.class ) { throw new SugarImporterException("BCSDB017", this.m_iPosition); } UnvalidatedGlycoNode t_objChildOne = (UnvalidatedGlycoNode)t_objOrginal.getGlycoNode(); UnvalidatedGlycoNode t_objChildTwo = (UnvalidatedGlycoNode)t_objSubtree.getGlycoNode(); if ( !t_objChildOne.getName().equals( t_objChildTwo.getName() ) ) { throw new SugarImporterException("BCSDB011", this.m_iPosition); } GlycoEdge t_objEdge = t_objOrginal.getGlycoEdge(); for (Iterator<Linkage> t_iterLinkages = t_objSubtree.getGlycoEdge().getGlycosidicLinkages().iterator(); t_iterLinkages.hasNext();) { t_objEdge.addGlycosidicLinkage(t_iterLinkages.next()); } if ( this.m_cToken != ']' ) { this.sidechain_follow(a_aSubLinkages,null,a_objSugar); } } else { // normal chain if ( a_objLastLinkage == null ) { throw new SugarImporterException("BCSDB013", this.m_iPosition); } // <residue> <linkage> [ <sidechain_follow> ] t_iStartPosition = this.m_iPosition; this.residue(); UnvalidatedGlycoNode t_objResiduum = new UnvalidatedGlycoNode(); t_objResiduum.setName( this.m_strText.substring( t_iStartPosition , this.m_iPosition ) ); a_objSugar.addNode(t_objResiduum); // attach sub residues a_objSugar.addEdge(t_objResiduum,a_objLastLinkage.getGlycoNode(),a_objLastLinkage.getGlycoEdge()); t_objSubtree = this.linkage(t_objResiduum,a_objSugar); if ( this.m_cToken != ']' ) { this.sidechain_follow(a_aSubLinkages,t_objSubtree,a_objSugar); } else { a_aSubLinkages.add(t_objSubtree); } } } public void setMinRepeatCount(int a_iCount) { this.m_iMinRepeatCount = a_iCount; } public void setMaxRepeatCount(int t_iCount) { this.m_iMaxRepeatCount = t_iCount; } }