/*
* 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: 1147 $ by $Author: glycoslave $ on $Date:: 2009-06-04 #$
*/
package org.eurocarbdb.sugar.seq.grammar;
// eurocarb imports
import org.eurocarbdb.util.graph.Graph;
import org.eurocarbdb.util.graph.Vertex;
import org.eurocarbdb.util.graph.Edge;
import org.eurocarbdb.util.graph.DepthFirstGraphVisitor;
import org.eurocarbdb.sugar.Sugar;
import org.eurocarbdb.sugar.Residue;
import org.eurocarbdb.sugar.Linkage;
/**
* Traverses an abstract syntax tree of a {@link Graph} of
* {@link LinkageToken}s and {@link ResidueToken}s and transforming
* it into a {@link Sugar} object. The visitor is started by
* calling {@link #visit(Graph)}.
* @author mjh
*/
public class AstTranslatorVisitor
extends DepthFirstGraphVisitor<LinkageToken,ResidueToken>
{
/** The Sugar to populate */
private final Sugar sugar;
/** Creates an AST walker to populate the given {@link Sugar} object */
public AstTranslatorVisitor( Sugar s )
{
this.sugar = s;
}
/**
* As we visit each edge in the AST, obtain the appropriate
* parent {@link Residue}, child {@link Residue}, and
* {@link Linkage} from the given edge, and add these into
* the nascent {@link Sugar}.
*/
public void accept( Edge<LinkageToken,ResidueToken> edge )
{
Linkage linkage = edge.getValue().getLinkage();
Vertex<LinkageToken,ResidueToken> ptok = edge.getParent();
Vertex<LinkageToken,ResidueToken> ctok = edge.getChild();
Residue parent = ptok.getValue().getResidue();
Residue child = ctok.getValue().getResidue();
if ( ! sugar.contains( parent ) )
{
sugar.addResidue( parent );
// optimisation only: pre-allocate exact number of edges for vertex
sugar.getGraph().lastVertex().ensureCapacity( ptok.countAttachedEdges() );
}
sugar.addResidue( parent, linkage, child );
// optimisation only: pre-allocate exact number of edges for vertex
sugar.getGraph().lastVertex().ensureCapacity( ctok.countAttachedEdges() );
super.accept( edge );
}
/**
* Although the traversal of {@link Edge}s is the primary means of
* adding residues/linkages to the {@link Sugar}, we still have
* to check {@link Vertex}es to make sure their {@link Residue}s
* also get added to the Sugar, since they may not have an {@link Edge}
* attached to them. A small optimisation is to make this check only for
* {@link Vertex}es that <em>don't</em> have edges, since vertices with
* edges will be added in {@link #visit(Edge)}.
*/
public void accept( Vertex<LinkageToken,ResidueToken> vertex )
{
if ( vertex.countAttachedEdges() == 0 )
{
Residue r = vertex.getValue().getResidue();
sugar.addResidue( r );
}
super.accept( vertex );
}
} // end class AstTranslatorVisitor