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     * Created on 01-21-2010
021     */
022    package org.biojava3.core.sequence.template;
023    
024    import java.util.ArrayList;
025    import java.util.Arrays;
026    import java.util.HashMap;
027    import java.util.HashSet;
028    import java.util.List;
029    import java.util.Map;
030    import java.util.Set;
031    
032    import org.biojava3.core.exceptions.CompoundNotFoundError;
033    
034    
035    /**
036     *
037     * @author Andy Yates
038     *
039     * @param <C> The compound this set will contain
040     */
041    public abstract class AbstractCompoundSet<C extends Compound> implements CompoundSet<C> {
042    
043      private Map<CharSequence, C> charSeqToCompound = new HashMap<CharSequence, C>();
044      private int maxCompoundCharSequenceLength = -1;
045      private Boolean compoundStringLengthEqual = null;
046      
047      Map<C,Set<C>> equivalentsMap = new HashMap<C, Set<C>>();
048    
049      protected void addCompound(C compound, C lowerCasedCompound, Iterable<C> equivalents) {
050        addCompound(compound);
051        addCompound(lowerCasedCompound);
052    
053        addEquivalent(compound, lowerCasedCompound);
054        addEquivalent(lowerCasedCompound, compound);
055    
056        for(C equivalent: equivalents) {
057          addEquivalent(compound, equivalent);
058          addEquivalent(equivalent, compound);
059          addEquivalent(lowerCasedCompound, equivalent);
060          addEquivalent(equivalent, lowerCasedCompound);
061        }
062      }
063    
064      protected void addCompound(C compound, C lowerCasedCompound, C... equivalents) {
065        List<C> equiv = new ArrayList<C>(equivalents.length);
066        equiv.addAll(Arrays.asList(equivalents));
067        addCompound(compound, lowerCasedCompound, equiv);
068      }
069    
070      protected void addEquivalent(C compound, C equivalent) {
071             Set<C> s = equivalentsMap.get(compound);
072             if ( s == null){
073                     s = new HashSet<C>();
074                     equivalentsMap.put(compound, s);
075             }
076              
077        s.add( equivalent);
078      }
079    
080      protected void addCompound(C compound) {
081        charSeqToCompound.put(compound.toString(), compound);
082        maxCompoundCharSequenceLength = -1;
083        compoundStringLengthEqual = null;
084      }
085    
086      public String getStringForCompound(C compound) {
087        return compound.toString();
088      }
089    
090      public C getCompoundForString(String string) {
091        if(string == null) {
092          throw new IllegalArgumentException("Given a null CharSequence to process");
093        }
094    
095        if (string.length()==0) {
096          return null;
097        }
098    
099        if (string.length() > getMaxSingleCompoundStringLength()) {
100          throw new IllegalArgumentException("CharSequence supplied is too long.");
101        }
102    
103        return charSeqToCompound.get(string);
104      }
105    
106      public int getMaxSingleCompoundStringLength() {
107        if(maxCompoundCharSequenceLength == -1) {
108          for(C compound: charSeqToCompound.values()) {
109            int size = getStringForCompound(compound).length();
110            if(size > maxCompoundCharSequenceLength) {
111              maxCompoundCharSequenceLength = size;
112            }
113          }
114        }
115        return maxCompoundCharSequenceLength;
116      }
117    
118        @Override
119        public boolean isCompoundStringLengthEqual() {
120            if(compoundStringLengthEqual == null) {
121                int lastSize = -1;
122                compoundStringLengthEqual = Boolean.TRUE;
123                for(CharSequence c: charSeqToCompound.keySet()) {
124                    int size = c.length();
125                    if(lastSize != -1) {
126                        lastSize = size;
127                        continue;
128                    }
129                    if(lastSize != size) {
130                        compoundStringLengthEqual = Boolean.FALSE;
131                        break;
132                    }
133                }
134            }
135            return compoundStringLengthEqual;
136        }
137    
138      public boolean hasCompound(C compound) {
139        C retrievedCompound = getCompoundForString(compound.toString());
140        return (retrievedCompound == null) ? false : true;
141      }
142    
143      public boolean compoundsEquivalent(C compoundOne, C compoundTwo) {
144        assertCompound(compoundOne);
145        assertCompound(compoundTwo);
146        return equivalentsMap.get(compoundOne).contains(compoundTwo);
147      }
148    
149      public Set<C> getEquivalentCompounds(C compound) {
150        return equivalentsMap.get(compound);
151      }
152    
153      public boolean compoundsEqual(C compoundOne, C compoundTwo) {
154        assertCompound(compoundOne);
155        assertCompound(compoundTwo);
156        return compoundOne.equalsIgnoreCase(compoundTwo);
157      }
158    
159      public void verifySequence(Sequence<C> sequence) throws CompoundNotFoundError {
160        for(C compound: sequence) {
161          assertCompound(compound);
162        }
163      }
164    
165      public List<C> getAllCompounds() {
166        return new ArrayList<C>(charSeqToCompound.values());
167      }
168    
169      private void assertCompound(C compound) {
170        boolean okay = hasCompound(compound);
171        if(! okay) {
172          throw new CompoundNotFoundError("The CompoundSet "+
173              getClass().getSimpleName()+" knows nothing about the compound "+
174              compound);
175        }
176      }
177    
178        @Override
179        public boolean isComplementable() {
180            return false;
181        }
182    }