/* * 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.Linucs; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import org.eurocarbdb.MolecularFramework.sugar.GlycoEdge; import org.eurocarbdb.MolecularFramework.sugar.GlycoconjugateException; import org.eurocarbdb.MolecularFramework.sugar.Linkage; import org.eurocarbdb.MolecularFramework.sugar.Monosaccharide; import org.eurocarbdb.MolecularFramework.sugar.NonMonosaccharide; import org.eurocarbdb.MolecularFramework.sugar.Substituent; import org.eurocarbdb.MolecularFramework.sugar.Sugar; import org.eurocarbdb.MolecularFramework.sugar.SugarUnitAlternative; import org.eurocarbdb.MolecularFramework.sugar.SugarUnitCyclic; import org.eurocarbdb.MolecularFramework.sugar.SugarUnitRepeat; import org.eurocarbdb.MolecularFramework.sugar.UnvalidatedGlycoNode; import org.eurocarbdb.MolecularFramework.util.traverser.GlycoTraverser; import org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor; import org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitorException; /** * @author Logan * */ public class GlycoVisitorExport implements GlycoVisitor { private String m_strCode = ""; private GlycoTraverser m_objTraverser = null; private boolean m_bFirstResidue = true; private SugarUnitRepeat m_objOuterRepeat = null; private HashMap<SugarUnitRepeat,String> m_hashAfterText = new HashMap<SugarUnitRepeat,String>(); private ArrayList<Integer> m_aParentPos = null; private ArrayList<Integer> m_aChildPos = null; private boolean m_bRepeatBefore = false; /** * @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#visit(org.eurocarbdb.MolecularFramework.sugar.Monosaccharide) */ public void visit(Monosaccharide a_objMonosaccharid) throws GlycoVisitorException { throw new GlycoVisitorException("Seems to be a wrong namespace. Linucs exporter does not support monosaccharide objects. Use UnvalidatedGlycoNode."); } /** * @see org.glycomedb.MolecularFrameWork.util.visitor.GlycoVisitor#visit(org.eurocarbdb.MolecularFramework.sugar.NonMonosaccharides) */ public void visit(NonMonosaccharide a_objResidue) throws GlycoVisitorException { throw new GlycoVisitorException("Seems to be a wrong namespace. Linucs exporter does not support nonmonosaccharide objects. Use UnvalidatedGlycoNode."); } /** * @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#visit(org.eurocarbdb.MolecularFramework.sugar.Substituent) */ public void visit(Substituent a_objSubstituent) throws GlycoVisitorException { throw new GlycoVisitorException("Seems to be a wrong namespace. Linucs exporter does not support substituent objects. Use UnvalidatedGlycoNode."); } /** * @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#visit(org.eurocarbdb.MolecularFramework.sugar.SugarUnitAlternative) */ public void visit(SugarUnitAlternative a_objAlternative) throws GlycoVisitorException { throw new GlycoVisitorException("Linucs exporter does not support alternative residue objects."); } /** * @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#start(org.eurocarbdb.MolecularFramework.sugar.Sugar) */ public void start(Sugar a_objSugar) throws GlycoVisitorException { try { if ( !a_objSugar.isConnected() ) { throw new GlycoVisitorException("Linucs does not support fragmented sugar."); } } catch (GlycoconjugateException e) { throw new GlycoVisitorException(e.getMessage(),e); } this.clear(); GlycoVisitorCyclic t_objVisitor = new GlycoVisitorCyclic(); t_objVisitor.start(a_objSugar); if ( t_objVisitor.getCyclic() == 0 ) { this.m_strCode = "[]"; this.m_objTraverser = new GlycoTraverserLinucs(this); this.m_objTraverser.traverseGraph(a_objSugar); } else if ( t_objVisitor.getCyclic() == 1 ) { this.m_strCode = "[][LINK]{[(UNTIL+"; this.writeLinkage( t_objVisitor.getChildPosition() ); this.m_strCode += ")]"; this.m_objTraverser = new GlycoTraverserLinucs(this); this.m_objTraverser.traverseGraph(a_objSugar); this.m_strCode += "}"; } else { throw new GlycoVisitorException("Linucs does not support multiple cyclic units."); } } /** * @throws GlycoVisitorException * @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#getTraverser(org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor) */ public GlycoTraverser getTraverser(GlycoVisitor a_objVisitor) throws GlycoVisitorException { return new GlycoTraverserLinucs(this); } /** * @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#clear() */ public void clear() { this.m_strCode = ""; this.m_bFirstResidue = true; this.m_objOuterRepeat = null; this.m_hashAfterText.clear(); this.m_aParentPos = null; this.m_aChildPos = null; this.m_bRepeatBefore = false; } /** * @return */ public String getCode() { return this.m_strCode; } /** * @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#visit(org.eurocarbdb.MolecularFramework.sugar.UnvalidatedGlycoNode) */ public void visit(UnvalidatedGlycoNode a_objUnvalidated) throws GlycoVisitorException { if ( this.m_objTraverser.getState() == GlycoTraverser.ENTER ) { if ( this.m_bFirstResidue ) { this.m_strCode += "[" + a_objUnvalidated.getName() + "]{"; this.m_bFirstResidue = false; } else { this.m_strCode += "[("; if ( this.m_bRepeatBefore ) { this.m_strCode += "<"; this.m_bRepeatBefore = false; } this.writeLinkage(this.m_aParentPos); this.m_strCode += "+"; this.writeLinkage(this.m_aChildPos); this.m_strCode += ")][" + a_objUnvalidated.getName() + "]{"; } } else { // LEAVE this.m_strCode += "}"; } } /** * @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#visit(org.eurocarbdb.MolecularFramework.sugar.GlycoEdge) */ public void visit(GlycoEdge a_objLinkage) throws GlycoVisitorException { if ( a_objLinkage.getGlycosidicLinkages().size() != 1 ) { throw new GlycoVisitorException("Linucs does not support multiple connected residues."); } for (Iterator<Linkage> t_iterLinkages = a_objLinkage.getGlycosidicLinkages().iterator(); t_iterLinkages.hasNext();) { Linkage t_objLink = t_iterLinkages.next(); this.m_aParentPos = t_objLink.getParentLinkages(); this.m_aChildPos = t_objLink.getChildLinkages(); } } /* (non-Javadoc) * @see org.glycomedb.MolecularFrameWork.util.visitor.GlycoVisitor#visit(org.glycomedb.MolecularFrameWork.sugar.SugarUnitCyclic) */ public void visit(SugarUnitCyclic a_objCyclic) throws GlycoVisitorException { if ( this.m_objTraverser.getState() == GlycoTraverser.ENTER ) { this.m_strCode += "[("; this.writeLinkage(this.m_aParentPos); this.m_strCode += "+CYCLIC)][LINK]{}"; } } /** * @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#visit(org.eurocarbdb.MolecularFramework.sugar.SugarUnitRepeat) */ public void visit(SugarUnitRepeat a_objRepeat) throws GlycoVisitorException { if ( this.m_objTraverser.getState() == GlycoTraverser.ENTER ) { if ( this.m_bFirstResidue ) { // sugar starts with a repeat this.m_objOuterRepeat = a_objRepeat; this.m_strCode += "[LINK]{[(UNTIL+"; GlycoEdge t_objEdge = a_objRepeat.getRepeatLinkage(); if ( t_objEdge.getGlycosidicLinkages().size() != 1 ) { throw new GlycoVisitorException("Linucs does not support multiple connected residues."); } if ( a_objRepeat.getChildEdges().size() != 0 ) { throw new GlycoVisitorException("Linucs support starting with a repeat unit for sugars that only consist of a repeat unit."); } Iterator<Linkage> t_aPositions = t_objEdge.getGlycosidicLinkages().iterator(); Linkage t_objLinkage = t_aPositions.next(); this.writeLinkage( t_objLinkage.getChildLinkages() ); this.m_strCode += ")]"; GlycoVisitorExportRepeat t_objRepeatVisitor = new GlycoVisitorExportRepeat(); t_objRepeatVisitor.start(a_objRepeat,t_objEdge); this.m_strCode += t_objRepeatVisitor.getBeforeCode() + "[("; this.writeLinkage( t_objLinkage.getParentLinkages() ); this.m_strCode += "+REPEAT)][LINK]{}"; this.m_strCode += t_objRepeatVisitor.getAfterCode(); this.m_strCode += "}"; this.m_bFirstResidue = false; } else { // inner repeat this.m_strCode += "[("; if ( this.m_bRepeatBefore ) { this.m_strCode += "<"; this.m_bRepeatBefore = false; } this.writeLinkage(this.m_aParentPos); this.m_strCode += "+"; this.writeLinkage(this.m_aChildPos); if ( a_objRepeat.getMinRepeatCount() != a_objRepeat.getMaxRepeatCount() ) { throw new GlycoVisitorException("LINUCS does not support repeat unit with different min and max count."); } if ( a_objRepeat.getMaxRepeatCount() == SugarUnitRepeat.UNKNOWN ) { this.m_strCode += ">N)]"; } else { this.m_strCode += ">" + String.format("%d",a_objRepeat.getMaxRepeatCount()) + ")]"; } if ( a_objRepeat.getRepeatLinkage().getGlycosidicLinkages().size() != 1 ) { throw new GlycoVisitorException("LINUCS does not support multivalent repeat units."); } Collections.sort( a_objRepeat.getRepeatLinkage().getGlycosidicLinkages().get(0).getChildLinkages() ); Collections.sort( a_objRepeat.getParentEdge().getGlycosidicLinkages().get(0).getChildLinkages() ); if ( !this.equalPositions( a_objRepeat.getRepeatLinkage().getGlycosidicLinkages().get(0).getChildLinkages(), a_objRepeat.getParentEdge().getGlycosidicLinkages().get(0).getChildLinkages()) ) { throw new GlycoVisitorException("LINUCS can not store differen child positions for internal and incoming repeat linkages"); } GlycoVisitorExportRepeat t_objExporter = new GlycoVisitorExportRepeat(); t_objExporter.start( a_objRepeat , a_objRepeat.getRepeatLinkage()); if ( a_objRepeat.getChildEdges().size() != 1 ) { throw new GlycoVisitorException("LINUCS can not store repeat units with more or less than one childbranch."); } Collections.sort( a_objRepeat.getRepeatLinkage().getGlycosidicLinkages().get(0).getParentLinkages() ); Collections.sort( a_objRepeat.getChildEdges().get(0).getGlycosidicLinkages().get(0).getParentLinkages() ); if ( !this.equalPositions( a_objRepeat.getRepeatLinkage().getGlycosidicLinkages().get(0).getParentLinkages(), a_objRepeat.getChildEdges().get(0).getGlycosidicLinkages().get(0).getParentLinkages()) ) { throw new GlycoVisitorException("LINUCS can not store differen parent positions for internal and outgoing repeat linkages"); } this.m_bRepeatBefore = true; this.m_strCode += t_objExporter.getBeforeCode(); this.m_hashAfterText.put(a_objRepeat,t_objExporter.getAfterCode()); } } else { // leave if ( this.m_objOuterRepeat != a_objRepeat ) { // end of inner repeat this.m_strCode += this.m_hashAfterText.get(a_objRepeat); } } } private void writeLinkage(ArrayList<Integer> a_aPositions) throws GlycoVisitorException { Collections.sort(a_aPositions); boolean t_bUnknown = false; if ( a_aPositions.size() < 1) { throw new GlycoVisitorException("Invalide linkage, no parent positions given."); } Iterator<Integer> t_iterPositions = a_aPositions.iterator(); Integer t_iPosition = t_iterPositions.next(); if ( t_iPosition == Linkage.UNKNOWN_POSITION ) { t_bUnknown = true; this.m_strCode += "?"; } else { this.m_strCode += t_iPosition.toString(); } while ( t_iterPositions.hasNext() ) { t_iPosition = t_iterPositions.next(); if ( t_iPosition == Linkage.UNKNOWN_POSITION || t_bUnknown ) { throw new GlycoVisitorException("Invalide linkage, unknown and distinct positions mixed."); } this.m_strCode += "/" + t_iPosition.toString(); } } /** * @param parentLinkages * @param parentLinkages2 * @return */ private boolean equalPositions(ArrayList<Integer> a_aLinkages, ArrayList<Integer> a_aLinkages2) { if ( a_aLinkages.size() == a_aLinkages2.size() ) { for (int i = 0; i < a_aLinkages.size(); i++) { if ( a_aLinkages.get(i) != a_aLinkages2.get(i) ) { return false; } } return true; } return false; } }