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 }