/* * 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.sugar; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitorException; import org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitorNodeType; public class GlycoGraphAlternative implements GlycoGraph { private ArrayList<GlycoNode> m_aResidues = new ArrayList<GlycoNode>(); private GlycoNode m_objLeadInNode = null; private HashMap<GlycoNode,GlycoNode> m_hLeadOutNodeToNode = new HashMap<GlycoNode,GlycoNode>(); /** * Delivers all Residues that does not have a parent residue. * @throws GlycoconjugateException if the structure contain a cyclic part or if the sugar contain no residue with a parent * @see de.glycosciences.glycoconjugate.GlycoGraph#getRootResiduesForNonCyclicSugars() */ public ArrayList<GlycoNode> getRootNodes() throws GlycoconjugateException { ArrayList<GlycoNode> t_aResult = new ArrayList<GlycoNode>(); GlycoNode t_objResidue; // for all residues of the sugar Iterator<GlycoNode> t_iterResidue = this.getNodeIterator(); while (t_iterResidue.hasNext()) { t_objResidue = t_iterResidue.next(); GlycoEdge t_objParents = t_objResidue.getParentEdge(); if ( t_objParents == null ) { t_aResult.add(t_objResidue); } } if ( t_aResult.size() < 1 ) { throw new GlycoconjugateException("Sugar seems not to have at least one root residue"); } return t_aResult; } /** * @see de.glycosciences.glycoconjugate.GlycoGraph#getResidueIterator() */ public Iterator<GlycoNode> getNodeIterator() { return this.m_aResidues.iterator(); } /** * @see de.glycosciences.MolecularFrameWork.sugar.GlycoGraph#isConnected() */ public boolean isConnected() throws GlycoconjugateException { ArrayList<GlycoNode> t_objRoots = this.getRootNodes(); if ( t_objRoots.size() > 1 ) { return false; } return true; } public boolean removeNode(GlycoNode a_objResidue) throws GlycoconjugateException { GlycoEdge t_objLinkage; GlycoNode t_objResidue; if ( a_objResidue == null ) { throw new GlycoconjugateException("Invalide residue."); } t_objLinkage = a_objResidue.getParentEdge(); if ( t_objLinkage != null ) { t_objResidue = t_objLinkage.getParent(); if ( t_objResidue == null ) { throw new GlycoconjugateException("A linkage with a null parent exists."); } t_objResidue.removeChildEdge(t_objLinkage); } for (Iterator<GlycoEdge> t_iterEdges = a_objResidue.getChildEdges().iterator(); t_iterEdges.hasNext();) { t_objLinkage = t_iterEdges.next(); t_objResidue = t_objLinkage.getChild(); if ( t_objResidue == null ) { throw new GlycoconjugateException("A linkage with a null child exists."); } t_objResidue.removeParentEdge(t_objLinkage); } return this.m_aResidues.remove(a_objResidue); } public ArrayList<GlycoNode> getNodes() { return this.m_aResidues; } /** * @see org.eurocarbdb.MolecularFramework.sugar.GlycoGraph#addNode(org.eurocarbdb.MolecularFramework.sugar.GlycoNode) */ public boolean addNode(GlycoNode a_objResidue) throws GlycoconjugateException { if ( a_objResidue == null ) { throw new GlycoconjugateException("Invalide residue."); } GlycoVisitorNodeType t_objNodeType = new GlycoVisitorNodeType(); if ( !this.m_aResidues.contains(a_objResidue) ) { try { if ( t_objNodeType.isSugarUnitCyclic(a_objResidue) ) { throw new GlycoconjugateException("Cyclic unit are not allowed in alternative graphs."); } if ( t_objNodeType.isSugarUnitRepeat(a_objResidue) ) { throw new GlycoconjugateException("repeat unit are not allowed in alternative graphs."); } if ( t_objNodeType.isSugarUnitAlternative(a_objResidue) ) { throw new GlycoconjugateException("Alternative units are not allowed in alternative graphs."); } } catch (GlycoVisitorException e) { throw new GlycoconjugateException(e.getMessage(),e); } a_objResidue.removeAllEdges(); return this.m_aResidues.add(a_objResidue); } return false; } /** * @see org.eurocarbdb.MolecularFramework.sugar.GlycoGraph#addNode(org.eurocarbdb.MolecularFramework.sugar.GlycoNode, org.eurocarbdb.MolecularFramework.sugar.GlycoEdge, org.eurocarbdb.MolecularFramework.sugar.GlycoNode) */ public boolean addNode(GlycoNode a_objParent, GlycoEdge a_objLinkage, GlycoNode a_objChild) throws GlycoconjugateException { if ( a_objParent == null || a_objChild == null ) { throw new GlycoconjugateException("Invalide residue."); } if ( a_objLinkage == null ) { throw new GlycoconjugateException("Invalide linkage."); } if ( a_objChild.getParentEdge() != null ) { throw new GlycoconjugateException("The child residue has a parent residue."); } this.addNode(a_objParent); this.addNode(a_objChild); if ( this.m_aResidues.contains(a_objChild) && this.m_aResidues.contains(a_objChild) ) { // test for indirect cyclic structures if ( this.isParent(a_objChild,a_objParent) || a_objChild == a_objParent ) { throw new GlycoconjugateException("Cyclic structures are not allowed in alternative glyco graphs."); } } else { throw new GlycoconjugateException("Critical error imposible to add residue."); } a_objChild.setParentEdge(a_objLinkage); a_objParent.addChildEdge(a_objLinkage); a_objLinkage.setChild(a_objChild); a_objLinkage.setParent(a_objParent); return true; } /** * @see org.eurocarbdb.MolecularFramework.sugar.GlycoGraph#addEdge(org.eurocarbdb.MolecularFramework.sugar.GlycoNode, org.eurocarbdb.MolecularFramework.sugar.GlycoNode, org.eurocarbdb.MolecularFramework.sugar.GlycoEdge) */ public boolean addEdge(GlycoNode a_objParent, GlycoNode a_objChild, GlycoEdge a_objLinkage) throws GlycoconjugateException { return this.addNode(a_objParent,a_objLinkage,a_objChild); } /** * @see org.eurocarbdb.MolecularFramework.sugar.GlycoGraph#containsNode(org.eurocarbdb.MolecularFramework.sugar.GlycoNode) */ public boolean containsNode(GlycoNode a_objNode) { return this.m_aResidues.contains(a_objNode); } /**Recursive check if query node has specified parent * @param child * @param parent * @return */ public boolean isParent(GlycoNode a_objParent, GlycoNode a_objNode) { GlycoNode t_objParent = a_objNode.getParentNode(); if ( t_objParent == null ) { return false; } if ( t_objParent == a_objParent ) { return true; } return this.isParent(a_objParent,t_objParent); } /** * @see org.eurocarbdb.MolecularFramework.sugar.GlycoGraph#removeEdge(org.eurocarbdb.MolecularFramework.sugar.GlycoEdge) */ public boolean removeEdge(GlycoEdge a_objEdge) throws GlycoconjugateException { GlycoNode t_objChild = a_objEdge.getChild(); GlycoNode t_objParent = a_objEdge.getParent(); if ( a_objEdge == null ) { return false; } if ( t_objChild == null || t_objParent == null ) { throw new GlycoconjugateException("The edge contains null values."); } if ( t_objChild.getParentEdge() != a_objEdge ) { throw new GlycoconjugateException("The child attachment is not correct"); } ArrayList<GlycoEdge> t_aEdges = t_objParent.getChildEdges(); if ( !t_aEdges.contains(a_objEdge) ) { throw new GlycoconjugateException("The parent attachment is not correct"); } t_objChild.removeParentEdge(a_objEdge); t_objParent.removeChildEdge(a_objEdge); return true; } public GlycoGraphAlternative copy() throws GlycoconjugateException { HashMap<GlycoNode,GlycoNode> t_hashResidues = new HashMap<GlycoNode,GlycoNode>(); GlycoGraphAlternative t_objCopy = new GlycoGraphAlternative(); GlycoNode t_objNodeOne; GlycoNode t_objNodeTwo; GlycoEdge t_objLinkOriginal; GlycoEdge t_objLinkCopy; ArrayList<GlycoEdge> t_aLinkages; // copy all nodes for (Iterator<GlycoNode> t_iterNode = this.m_aResidues.iterator(); t_iterNode.hasNext();) { t_objNodeOne = t_iterNode.next(); t_objNodeTwo = t_objNodeOne.copy(); t_hashResidues.put(t_objNodeOne,t_objNodeTwo); t_objCopy.addNode(t_objNodeTwo); } // copy linkages for (Iterator<GlycoNode> t_iterNode = this.m_aResidues.iterator(); t_iterNode.hasNext();) { t_objNodeOne = t_iterNode.next(); t_aLinkages = t_objNodeOne.getChildEdges(); for (Iterator<GlycoEdge> t_iterLinkages = t_aLinkages.iterator(); t_iterLinkages.hasNext();) { t_objLinkOriginal = t_iterLinkages.next(); t_objLinkCopy = t_objLinkOriginal.copy(); t_objNodeOne = t_hashResidues.get(t_objLinkOriginal.getParent()); t_objNodeTwo = t_hashResidues.get(t_objLinkOriginal.getChild()); if ( t_objNodeOne == null || t_objNodeTwo == null ) { throw new GlycoconjugateException("Impossible to copy alternative glyco graph. Null values in copy."); } t_objCopy.addEdge( t_objNodeOne, t_objNodeTwo, t_objLinkCopy); } } // copy parent connection information if ( this.m_objLeadInNode != null ) { t_objCopy.setLeadInNode( t_hashResidues.get(this.m_objLeadInNode) ); } // copy child connection information for (Iterator<GlycoNode> t_iterChilds = this.m_hLeadOutNodeToNode.keySet().iterator(); t_iterChilds.hasNext();) { GlycoNode t_objChild = t_iterChilds.next(); t_objNodeOne = t_hashResidues.get(this.m_hLeadOutNodeToNode.get(t_objChild)); if ( t_objNodeOne == null ) { throw new GlycoconjugateException("Impossible to copy child connection. Null values in copy."); } t_objCopy.addLeadOutNodeToNode(t_objChild,t_objNodeOne); } return t_objCopy; } protected void setLeadInNode(GlycoNode a_objNode) throws GlycoconjugateException { if ( !this.m_aResidues.contains(a_objNode) ) { throw new GlycoconjugateException("Parent residue is not part of the glyco graph."); } this.m_objLeadInNode = a_objNode; } public GlycoNode getLeadInNode() { return this.m_objLeadInNode; } protected void addLeadOutNodeToNode(GlycoNode a_objChildResidue, GlycoNode a_objNode) throws GlycoconjugateException { if ( !this.m_aResidues.contains(a_objNode) ) { throw new GlycoconjugateException("Child residue is not part of the glyco graph."); } this.m_hLeadOutNodeToNode.put(a_objChildResidue,a_objNode); } public HashMap<GlycoNode,GlycoNode> getLeadOutNodeToNode() { return this.m_hLeadOutNodeToNode; } public boolean removeLeadOutNodeToNode(GlycoEdge a_objEdge, GlycoNode a_objNode) { if ( !this.m_hLeadOutNodeToNode.containsKey(a_objEdge) ) { return false; } if ( this.m_hLeadOutNodeToNode.get(a_objEdge) != a_objNode ) { return false; } this.m_hLeadOutNodeToNode.remove(a_objEdge); return true; } /** * */ public void removeAllLeadOutNodes() { this.m_hLeadOutNodeToNode.clear(); } }