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 * <p> 033 * The mapping between the alphabets can be either 034 * one-to-one or many-to one. 035 * 036 * @author David Huen 037 */ 038public abstract class AbstractManyToOneTranslationTable 039 extends AbstractTranslationTable 040 implements ManyToOneTranslationTable 041{ 042 public abstract Alphabet getSourceAlphabet(); 043 public abstract Alphabet getTargetAlphabet(); 044 /** 045 * this method is expected to reverse-translate any symbol 046 * in the source alphabet. Failure can be indicated 047 * by returning a null if, for example, your method 048 * only handles AtomicSymbols and you want BasisSymbols 049 * to be taken apart. If you are sure the symbol is 050 * illegal, you can throw the IllegalSymbolException 051 * immediately to bypass further processing. 052 053 * <p> 054 * As an optimisation, if your method is capable of 055 * immediately translating an ambiguity Symbol, just 056 * return it and the alternate route of establishing 057 * the translation through doing an ambiguity 058 * lookup will be avoided. 059 */ 060 protected abstract Set doUntranslate(Symbol sym) throws IllegalSymbolException; 061 062 /** 063 * returns a Set of Atomic Symbols that are the reverse translation 064 * of the specified Symbol in the target alphabet. 065 */ 066 public Set untranslate(final Symbol sym) 067 throws IllegalSymbolException { 068 // make an attempt to translate immediately 069 Set s = doUntranslate(sym); 070 071 // translation failed, validate and try an ambiguity lookup 072 if(s == null) { 073 if(sym instanceof AtomicSymbol) { //changed this from s to sym, since we already checked and s is null 074 getSourceAlphabet().validate(sym); 075 076 // the symbol was valid and still we can't handle it, bail out! 077 throw new IllegalSymbolException("Unable to map " + sym.getName()); 078 } else { 079 if(sym == null) { 080 throw new NullPointerException("Can't translate null"); 081 } 082 s = new HashSet(); 083 for (Iterator i = ((FiniteAlphabet) sym.getMatches()).iterator(); i.hasNext(); ) { 084 Symbol is = (Symbol) i.next(); 085 s.add(this.untranslate(is)); 086 } 087 } 088 } 089 return s; 090 } 091}