/*
* 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.GlycoNode;
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 GlycoVisitorExportRepeat implements GlycoVisitor
{
private String m_strBefore = "";
private String m_strAfter = "";
private String m_strCode = "";
private GlycoTraverserLinucs m_objTraverser = null;
private GlycoNode m_objResidueEnd = null;
private GlycoNode m_objResidueStart = null;
private ArrayList<Integer> m_aParentPos = null;
private ArrayList<Integer> m_aChildPos = null;
private boolean m_bRepeatBefore = false;
private HashMap<SugarUnitRepeat,String> m_hashAfterText = new HashMap<SugarUnitRepeat,String>();
private boolean m_bFirstResidue = true;
/**
* @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
{
throw new GlycoVisitorException("Not possible to visit sugar, only repeat units.");
}
public void start(SugarUnitRepeat a_objRepeat, GlycoEdge a_objOut) throws GlycoVisitorException
{
this.clear();
this.m_objResidueStart = a_objRepeat.getRepeatLinkage().getChild();
this.m_objResidueEnd = a_objRepeat.getRepeatLinkage().getParent();
// nur ein residue
ArrayList<GlycoNode> t_aRoots;
try
{
t_aRoots = a_objRepeat.getRootNodes();
if ( t_aRoots.size() != 1 )
{
throw new GlycoVisitorException("Linucs exporter does not support fragmented repeat units.");
}
// muss gleich start sein
if ( t_aRoots.get(0) != this.m_objResidueStart )
{
throw new GlycoVisitorException("Invalide repeat unit (start and root residue does not match).");
}
}
catch (GlycoconjugateException e)
{
throw new GlycoVisitorException(e.getMessage(),e);
}
this.m_objTraverser = this.getTraverser(this);
this.m_objTraverser.traverseGraph(a_objRepeat,a_objOut,this);
this.m_strAfter = this.m_strCode;
}
/**
* @throws GlycoVisitorException
* @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#getTraverser(org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor)
*/
public GlycoTraverserLinucs getTraverser(GlycoVisitor a_objVisitor) throws GlycoVisitorException
{
return new GlycoTraverserLinucs(this);
}
/**
* @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#clear()
*/
public void clear()
{
this.m_strBefore = "";
this.m_strAfter = "";
this.m_strCode = "";
this.m_objTraverser = null;
this.m_objResidueEnd = null;
this.m_objResidueStart = null;
this.m_bRepeatBefore = false;
this.m_hashAfterText.clear();
this.m_bFirstResidue = true;
}
/**
* @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();
}
}
/**
* @see org.eurocarbdb.MolecularFramework.util.visitor.GlycoVisitor#visit(org.eurocarbdb.MolecularFramework.sugar.SugarUnitCyclic)
*/
public void visit(SugarUnitCyclic a_objCyclic) throws GlycoVisitorException
{
throw new GlycoVisitorException("Linucs does not support cyclic part in repeat units.");
}
/**
* @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 ( a_objRepeat == this.m_objResidueStart )
{
throw new GlycoVisitorException("LINUCS does not support nested repeat unit at the start residue.");
}
if ( a_objRepeat == this.m_objResidueEnd )
{
throw new GlycoVisitorException("LINUCS does not support nested repeat unit at the end residue.");
}
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() );
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() );
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
this.m_strCode += this.m_hashAfterText.get(a_objRepeat);
}
}
/**
* @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;
}
private void writeLinkage(ArrayList<Integer> a_aPositions) throws GlycoVisitorException
{
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();
}
}
public String getBeforeCode()
{
return this.m_strBefore;
}
public String getAfterCode()
{
return this.m_strAfter;
}
public void switchStrings()
{
this.m_strBefore = this.m_strCode;
this.m_strCode = "";
}
}