001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021 022package org.biojava.bio.symbol; 023 024import java.util.HashSet; 025import java.util.Iterator; 026import java.util.Set; 027 028/** 029 * an abstract class implementing basic functionality 030 * of a translation table that translates Symbols from 031 * one Alphabet to another. 032 * 033 * @author Matthew Pocock 034 * @author Keith James (docs) 035 * @author Thomas Down 036 * @author Greg Cox 037 * @author Mark Schreiber 038 * @author David Huen (refactoring) 039 */ 040public abstract class AbstractReversibleTranslationTable 041 extends AbstractTranslationTable 042 implements ReversibleTranslationTable 043{ 044 public abstract Alphabet getSourceAlphabet(); 045 public abstract Alphabet getTargetAlphabet(); 046 /** 047 * this method is expected to reverse-translate any symbol 048 * in the source alphabet. Failure can be indicated 049 * by returning a null if, for example, your method 050 * only handles AtomicSymbols and you want BasisSymbols 051 * to be taken apart. If you are sure the symbol is 052 * illegal, you can throw the IllegalSymbolException 053 * immediately to bypass further processing. 054 055 * <p> 056 * As an optimisation, if your method is capable of 057 * immediately translating an ambiguity Symbol, just 058 * return it and the alternate route of establishing 059 * the translation through doing an ambiguity 060 * lookup will be avoided. 061 */ 062 protected abstract Symbol doUntranslate(Symbol sym) throws IllegalSymbolException; 063 064 public Symbol untranslate(final Symbol sym) 065 throws IllegalSymbolException { 066 // make an attempt to translate immediately 067 Symbol s = doUntranslate(sym); 068 069 // translation failed, validate and try an ambiguity lookup 070 if(s == null) { 071 if(sym instanceof AtomicSymbol) { //changed this from s to sym, since we already checked and s is null 072 getSourceAlphabet().validate(sym); 073 074 // the symbol was valid and still we can't handle it, bail out! 075 throw new IllegalSymbolException("Unable to map " + sym.getName()); 076 } else { 077 if(sym == null) { 078 throw new NullPointerException("Can't translate null"); 079 } 080 Set syms = new HashSet(); 081 for (Iterator i = ((FiniteAlphabet) sym.getMatches()).iterator(); i.hasNext(); ) { 082 Symbol is = (Symbol) i.next(); 083 syms.add(this.untranslate(is)); 084 } 085 s = getTargetAlphabet().getAmbiguity(syms); 086 } 087 } 088 return s; 089 } 090}