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.Iterator;
025import java.util.Set;
026
027import org.biojava.bio.seq.DNATools;
028import org.biojava.utils.AssertionFailure;
029import org.biojava.utils.SmallSet;
030
031/**
032 * Packing utility class for DNA.  Also represents
033 * ambiguity.
034 *
035 * @author Matthew Pocock
036 * @author David Huen (bugfix)
037 */  
038public class DNAAmbPack
039  implements
040    Packing,
041    java.io.Serializable
042{
043  private final Symbol[] syms;
044  
045  public DNAAmbPack() {
046    this.syms = new Symbol[16];
047    for(byte i = 0; i < 16; i++) {
048      syms[i] = _unpack(i);
049    }
050  }
051  
052  public FiniteAlphabet getAlphabet() {
053    return DNATools.getDNA();
054  }
055  
056  public byte pack(Symbol sym) {
057    if(false) {
058    } else if(sym == DNATools.a()) {
059      return 1;
060    } else if(sym == DNATools.g()) {
061      return 2;
062    } else if(sym == DNATools.c()) {
063      return 4;
064    } else if(sym == DNATools.t()) {
065      return 8;
066    } else if(sym == DNATools.n()) {
067      return 15;
068    }
069    
070    byte p = 0;
071    for(Iterator i = ((FiniteAlphabet) sym.getMatches()).iterator(); i.hasNext(); ) {
072      p |= pack((AtomicSymbol) i.next());
073    }
074    return p;
075  }
076  
077  public Symbol unpack(byte b) {
078    return syms[b];
079  }
080  
081  private Symbol _unpack(byte b) {
082    Set syms = new SmallSet();
083    if(0 != (b & 1)) {
084      syms.add(DNATools.a());
085    }
086    if(0 != (b & 2)) {
087      syms.add(DNATools.g());
088    }
089    if(0 != (b & 4)) {
090      syms.add(DNATools.c());
091    }
092    if(0 != (b & 8)) {
093      syms.add(DNATools.t());
094    }
095    try {
096      // do incorporate the gap symbol when appropriate
097      if (b != 0)
098          return DNATools.getDNA().getAmbiguity(syms);
099      else
100          return DNATools.getDNA().getGapSymbol();
101
102    } catch (IllegalSymbolException ise) {
103      throw new AssertionFailure("Assertion failure: couldn't get DNA ambiguity from DNA: " + syms, ise);
104    }
105  }
106  
107  public byte wordSize() {
108    return 4;
109  }
110  
111  public boolean handlesAmbiguity() {
112    return true;
113  }
114}
115