/* * 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.resourcesdb.io; import java.util.ArrayList; import org.eurocarbdb.resourcesdb.Config; import org.eurocarbdb.resourcesdb.GlycanNamescheme; import org.eurocarbdb.resourcesdb.ResourcesDbException; import org.eurocarbdb.resourcesdb.ResourcesDbObject; import org.eurocarbdb.resourcesdb.glycoconjugate_derived.LinkageType; import org.eurocarbdb.resourcesdb.monosaccharide.*; import org.eurocarbdb.resourcesdb.template.SubstituentTemplate; import org.eurocarbdb.resourcesdb.template.TemplateContainer; import org.eurocarbdb.resourcesdb.template.TrivialnameTemplate; /** * A basic MonosaccharideImporter class, providing a number of fields and methods that are needed in most importers. * * @author Thomas Luetteke */ public abstract class StandardImporter extends ResourcesDbObject { private String inputName; private boolean foundMs; private int parsingPosition = 0; private GlycanNamescheme namescheme; private String tmpStereocode; private TrivialnameTemplate detectedTrivialname; //***************************************************************************** //*** constructors: *********************************************************** //***************************************************************************** public StandardImporter(GlycanNamescheme scheme, Config confObj) { this(null, null, null); } public StandardImporter(GlycanNamescheme scheme, Config confObj, TemplateContainer container) { this.namescheme = scheme; this.setConfig(confObj); this.setTemplateContainer(container); this.inputName = null; this.foundMs = false; } public StandardImporter() { this(null, null); } //***************************************************************************** //*** getters/setters: ******************************************************** //***************************************************************************** public GlycanNamescheme getNamescheme() { return this.namescheme; } public void setNamescheme(GlycanNamescheme scheme) { this.namescheme = scheme; } /** * @return the foundMs */ public boolean isFoundMs() { return this.foundMs; } /** * @param foundMs the foundMs to set */ protected void setFoundMs(boolean foundMs) { this.foundMs = foundMs; } /** * @return the inputName */ public String getInputName() { return this.inputName; } /** * @param inputName the inputName to set */ public void setInputName(String inputName) { this.inputName = inputName; } /** * @return the tmpStereocode */ protected String getTmpStereocode() { return this.tmpStereocode; } /** * @param tmpStereocode the tmpStereocode to set */ protected void setTmpStereocode(String tmpStereocode) { this.tmpStereocode = tmpStereocode; } /** * Get the current parsing position * @return the current parsing position */ protected int getParsingPosition() { return this.parsingPosition; } /** * Set the current parsing position * @param ppos the position to set */ protected void setParsingPosition(int ppos) { this.parsingPosition = ppos; } /** * Increase the current parsing position by 1 */ protected void increaseParsingPosition() { this.parsingPosition ++; } /** * Increase the current parsing position by a given value * @param steps the value to add to the parsing position */ protected void increaseParsingPosition(int steps) { this.parsingPosition += steps; } public TrivialnameTemplate getDetectedTrivialname() { return detectedTrivialname; } public void setDetectedTrivialname(TrivialnameTemplate detectedTrivialname) { this.detectedTrivialname = detectedTrivialname; } //***************************************************************************** //*** parsing methods: ******************************************************** //***************************************************************************** /** * Returns the character that is in the <code>inputName</code> at the current <code>ParsingPosition</code> * @throws NameParsingException in case the current <code>parsingPosition</code> is out of range * @return the value of <code>getInputName().charAt(getParsingPosition())</code> */ protected char getCurrentToken() throws NameParsingException { if(this.getInputName().length() <= this.getParsingPosition()) { throw new NameParsingException("unexpected end of string", this.getInputName(), this.getParsingPosition()); } return this.getInputName().charAt(this.getParsingPosition()); } /** * Get a Substring of <code>inputName</code> starting at the current <code>parsingPosition</code>. * The <code>parsingPosition</code> is not changed by this method. * @param length the length of the substring to return * @throws NameParsingException in case (part of) the resulting substring is out of range of the <code>inputName</code> * @return the Substring of <code>inputName</code> name starts at <code>parsingPosition</code> and has the given length */ protected String getCurrentSubstring(int length) throws NameParsingException { if(this.getInputName().length() < this.getParsingPosition() + length) { throw new NameParsingException("unexpected end of string", this.getInputName(), this.getParsingPosition()); } return this.getInputName().substring(this.getParsingPosition(), this.getParsingPosition() + length); } protected boolean hasCurrentSubstring(String cmpString) { try { return this.getCurrentSubstring(cmpString.length()).equals(cmpString); } catch(NameParsingException npe) { return false; } } /** * Increases the current <code>parsingPosition</code> and returns the character that is in the <code>inputName</code> at the resulting <code>ParsingPosition</code> * @throws NameParsingException in case the current <code>parsingPosition</code> is out of range * @return the character following the current <code>parsingPosition</code> */ protected char getNextToken() throws NameParsingException { this.increaseParsingPosition(); if(this.getInputName().length() <= this.getParsingPosition()) { throw new NameParsingException("unexpected end of string", this.getInputName(), this.getParsingPosition()); } return this.getInputName().charAt(this.getParsingPosition()); } /** * Check, if the <code>inputName</code> has a character after the current <code>parsingPosition</code> * @return */ protected boolean hasNextToken() { return this.getInputName() != null && this.getParsingPosition() + 1 < this.getInputName().length(); } /** * Get the number of remaining tokens in <code>inputName</code>, starting with the current parsing position * @return */ protected int countRemainingTokens() { if(this.getInputName() == null) { return -1; } return this.getInputName().length() - this.getParsingPosition(); } /** * Check, if the <code>inputName</code> has a character at the current <code>parsingPosition</code> * (i.e. if the current <code>parsingPosition</code> is within the length range of <code>inputName</code>) * @return true, if 0 <= parsingPosition < inputName.length */ protected boolean hasCurrentToken() { return this.getInputName() != null && this.getParsingPosition() < this.getInputName().length() && this.getParsingPosition() >= 0; } protected int parseIntNumber() throws NameParsingException { return parseIntNumber(false); } protected int parseIntNumber(boolean allowWildcard) throws NameParsingException { if(allowWildcard && this.getCurrentToken() == '?') { this.increaseParsingPosition(); return 0; } String numberString = ""; while(this.hasCurrentToken() && Character.isDigit(this.getCurrentToken())) { numberString += this.getCurrentToken(); this.increaseParsingPosition(); } if(numberString.length()==0) { throw new NameParsingException("number expected ", this.getInputName(), this.getParsingPosition()); } return Integer.parseInt(numberString); } protected ArrayList<Integer> parseIntNumberList() throws NameParsingException { return parseIntNumberList(false); } protected ArrayList<Integer> parseIntNumberList(boolean allowWildcard) throws NameParsingException { ArrayList<Integer> outList = new ArrayList<Integer>(); int num = parseIntNumber(allowWildcard); outList.add(new Integer(num)); while(this.hasCurrentToken() && this.getCurrentToken() == ',') { this.increaseParsingPosition(); num = parseIntNumber(allowWildcard); outList.add(new Integer(num)); } return outList; } /** * Check, if the <code>inputName</code> contains a trivial name at the current <code>parsingPosition</code>. * If more than one matching trivial names are found (e.g. "G" and "GN" in CFG notation), the longest one is retured. * The <code>parsingPosition</code> is not changed by this method. * @return the detected trivial name or null if no match is found * @throws ResourcesDbException */ protected String checkForTrivialname() throws ResourcesDbException { String detectedTrivName = null; for(String trivName : this.getTemplateContainer().getTrivialnameTemplateContainer().getTrivialnameBasetypeList(this.getNamescheme())) { if(detectedTrivName != null && detectedTrivName.length() >= trivName.length()) { continue; } if(this.getInputName().length() - this.getParsingPosition() >= trivName.length()) { if(this.getInputName().substring(this.getParsingPosition(), this.getParsingPosition() + trivName.length()).equals(trivName)) { detectedTrivName = trivName; } } } return detectedTrivName; } //***************************************************************************** //*** other methods: ********************************************************** //***************************************************************************** /** * Initialize a substitution with data parsed from a residue name and add it to a Monosaccharide * @param ms the Monosaccharide, to which the substition shall be added * @param parsedName the substituent name as it is present in the residue * @param posList a list of subsituent position as parsed from the residue * @throws ResourcesDbException */ protected void addParsedSubstitution(Monosaccharide ms, String parsedName, ArrayList<Integer> posList) throws ResourcesDbException { SubstituentTemplate substTmpl = this.getTemplateContainer().getSubstituentTemplateContainer().forResidueIncludedName(this.getNamescheme(), parsedName); if(substTmpl == null) { throw new ResourcesDbException("internal error: cannot get template for substituent " + parsedName); } LinkageType linktype1 = substTmpl.getLinkageTypeBySubstituentName(this.getNamescheme(), parsedName); if(substTmpl.getMaxValence() == 1 || (posList.size() == 1 && substTmpl.getMinValence() == 1)) { for(Integer pos : posList) { Substitution subst = new Substitution(); subst.setSubstitution(substTmpl, pos, linktype1); subst.setSourceName(parsedName); ms.addSubstitution(subst); } } else if(substTmpl.getMaxValence() == 2) { if(posList.size() != 2) { throw new NameParsingException("Only one position given for divalent substituent " + parsedName, this.getInputName(), this.getParsingPosition()); } LinkageType linktype2 = substTmpl.getLinkageType2BySubstituentName(this.getNamescheme(), parsedName); Substitution subst = new Substitution(); subst.setDivalentSubstitution(substTmpl, posList.get(0), linktype1, substTmpl.getDefaultLinkingPosition1(), posList.get(1), linktype2, substTmpl.getDefaultLinkingPosition2()); subst.setSourceName(parsedName); ms.addSubstitution(subst); } } public void init() { this.setInputName(null); this.setParsingPosition(0); this.setFoundMs(false); this.setTmpStereocode(null); this.setDetectedTrivialname(null); } }