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
022
023package org.biojava.bio.symbol;
024
025import java.io.Serializable;
026import java.util.HashMap;
027import java.util.HashSet;
028import java.util.Map;
029import java.util.Set;
030
031/**
032 * A no-frills implementation of a translation table that
033 * maps between two alphabets.  The mapping can be either
034 * one-to-one or many-to-one.
035 *
036 * @author David Huen
037 */
038public class SimpleManyToOneTranslationTable
039      extends AbstractManyToOneTranslationTable
040      implements Serializable {
041  private final Map transMap;
042  private final Map revMap;
043  private final FiniteAlphabet source;
044  private final Alphabet target;
045
046  public Alphabet getSourceAlphabet() {
047    return source;
048  }
049
050  public Alphabet getTargetAlphabet() {
051    return target;
052  }
053
054  protected Symbol doTranslate(Symbol sym) {
055    return (Symbol) transMap.get(sym);
056  }
057
058  protected Set doUntranslate(Symbol sym) {
059    return (Set) revMap.get(sym);
060  }
061
062  /**
063   * Alter the translation mapping.
064   *
065   * @param from source AtomicSymbol
066   * @param to   target AtomicSymbol to be returned by translate(from)
067   * @throws IllegalSymbolException if either from is not in the source
068   *         alphabet or to is not in the target alphabet
069   */
070  public void setTranslation(AtomicSymbol from, AtomicSymbol to)
071  throws IllegalSymbolException {
072
073    source.validate(from);
074    target.validate(to);
075
076    // when putting in a association in a many-to-one
077    // you will need to verify that an existing relation does
078    // not exist: otherwise you will need to remove it prior
079    // to putting in the new one.
080
081    // do I have an existing association for this symbol?
082    Symbol prevTransSymbol = doTranslate(from);
083
084    if (prevTransSymbol != null) {
085        // there is an association, I need to
086        // remove the previous target Symbol
087        // from the unTranslate mapping
088        // before introducing new mapping.
089
090        Set prevUntransSet = (Set) revMap.get(prevTransSymbol);
091        prevUntransSet.remove(from);
092    }
093
094    // now enter in the new association
095    Set sourceSet = (Set) revMap.get(to);
096
097    if (sourceSet == null) {
098        // create new set
099        sourceSet = new HashSet();
100        revMap.put(to, sourceSet);
101    }
102
103    sourceSet.add(from);
104
105    transMap.put(from, to);
106
107  }
108
109  /**
110   * Construct a new translation table.
111   *
112   * @param source  the source FiniteAlphabet
113   * @param target the target FiniteAlphabet
114   */
115  public SimpleManyToOneTranslationTable(FiniteAlphabet source, FiniteAlphabet target)
116  {
117
118    this.source = source;
119    this.target = target;
120    this.transMap = new HashMap();
121    this.revMap = new HashMap();
122  }
123}