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.seq.db; 023 024import java.util.HashMap; 025import java.util.HashSet; 026import java.util.Iterator; 027import java.util.Map; 028import java.util.Set; 029 030import org.biojava.utils.ObjectUtil; 031 032/** 033 * This class is an implementation of interface SequenceDBInstallation 034 * that manages a set of SequenceDB objects. The set of SequenceDB 035 * objects is initially empty and can be expanded by the user through 036 * the addSequenceDB() method. This SequenceDBInstallation is then 037 * able to serve the SequenceDB objects in this set. 038 * 039 * @author Keith James 040 * @author <a href="mailto:Gerald.Loeffler@vienna.at">Gerald 041 * Loeffler</a> (primary author) for the <a//href= 042 * "http://www.imp.univie.ac.at">IMP</a> 043 */ 044public class SimpleSequenceDBInstallation implements SequenceDBInstallation 045{ 046 private Map sequenceDBByIdentifier = new HashMap(); 047 048 /** 049 * create an initially empty SimpleSequenceDBInstallation 050 */ 051 public SimpleSequenceDBInstallation() { } 052 053 /** 054 * This method creates a new (and empty) HashSequenceDB with the 055 * given name that will be accessible through this sequence db 056 * installation through this name and all given other identifiers. 057 * @param name the name of the SequenceDB to create. Not null. If 058 * this name is already used by this sequence db installation, an 059 * IllegalArgumentException is thrown. 060 * @param otherIdentifiers a set of String objects that also serve 061 * as identifiers for the newly created SequenceDB object. This set 062 * should not contain the name of the SequenceDB, but if if does, it 063 * is just ignored because the name is an identifier by 064 * definition. The parameter may be empty or the empty set, in which 065 * case the name is the only identifier for the newly created 066 * SequenceDB. If any of the given identifiers (including the name) 067 * is already used by this SimpleSequenceDBInstallation, an 068 * IllegalArgumentException is thrown. 069 */ 070 public synchronized void addSequenceDB(String name, Set otherIdentifiers) 071 { 072 if (name == null) { 073 throw new IllegalArgumentException("name was null"); 074 } 075 // otherIdentifiers may only contain String objects - but this is checked later 076 077 // create set of all identifiers for the to-be-created SequenceDB 078 Set allIdentifiers = new HashSet(); 079 allIdentifiers.add(name); 080 if (otherIdentifiers != null) allIdentifiers.addAll(otherIdentifiers); 081 082 // none of the identifiers may already be in use 083 Set currentIdentifiers = this.sequenceDBByIdentifier.keySet(); 084 for (Iterator i = allIdentifiers.iterator(); i.hasNext();) 085 { 086 Object o = i.next(); 087 if (! (o instanceof String)) { 088 throw new IllegalArgumentException("otherIdentifiers must be a Set of String objects"); 089 } 090 if (currentIdentifiers.contains(o)) { 091 throw new IllegalArgumentException("name and otherIdentifiers must not already be in use"); 092 } 093 } 094 095 // create new HashSequenceDB and at it to the map under all its identifiers 096 SequenceDB db = new HashSequenceDB(name); 097 for (Iterator i = allIdentifiers.iterator(); i.hasNext();) 098 { 099 String identifier = (String) i.next(); 100 this.sequenceDBByIdentifier.put(identifier, db); 101 } 102 } 103 104 /** 105 * <code>addSequenceDB</code> adds a new SequenceDB which will be 106 * accessible via the name returned by its getName() method and 107 * via all other given identifiers. 108 * 109 * @param sequenceDB a <code>SequenceDB</code> object to 110 * add. Although a SequenceDB may normally have a null name this 111 * is not acceptable when it is added to a 112 * SimpleSequenceDBInstallation as the name is used as its primary 113 * identifier. If the name is already used by this 114 * SimpleSequenceDBInstallation, an IllegalArgumentException is 115 * thrown. 116 * @param otherIdentifiers a <code>Set</code> of String objects 117 * that also serve as identifiers for the newly created 118 * SequenceDB. This set should not contain the name of the 119 * SequenceDB, but if if does, it is just ignored because the name 120 * is an identifier by definition. The parameter may be empty or 121 * the empty set, in which case the name is the only identifier 122 * for the newly created SequenceDB. If any of the given 123 * identifiers (including the name) is already used by this 124 * sequence db installation, an IllegalArgumentException is 125 * thrown. 126 */ 127 public synchronized void addSequenceDB(SequenceDBLite sequenceDB, 128 Set otherIdentifiers) 129 { 130 if (sequenceDB == null) { 131 throw new IllegalArgumentException("SequenceDB was null"); 132 } 133 134 // The SequenceDB name may not be null 135 String name = sequenceDB.getName(); 136 137 // Create set of all identifiers for the to-be-added SequenceDB 138 Set allIdentifiers = new HashSet(); 139 allIdentifiers.add(name); 140 if (otherIdentifiers != null) allIdentifiers.addAll(otherIdentifiers); 141 142 // None of the identifiers may already be in use 143 Set currentIdentifiers = this.sequenceDBByIdentifier.keySet(); 144 for (Iterator i = allIdentifiers.iterator(); i.hasNext();) 145 { 146 Object o = i.next(); 147 if (! (o instanceof String)) { 148 throw new IllegalArgumentException("otherIdentifiers must be a set of String objects"); 149 } 150 if (currentIdentifiers.contains(o)) { 151 throw new IllegalArgumentException("name and otherIdentifiers must not already be in use"); 152 } 153 } 154 155 // Add the SequenceDB to the map under all its identifiers 156 for (Iterator i = allIdentifiers.iterator(); i.hasNext();) 157 { 158 String identifier = (String) i.next(); 159 this.sequenceDBByIdentifier.put(identifier, sequenceDB); 160 } 161 } 162 163 /** 164 * Return a newly created set of the SequenceDB objects that were 165 * already created through method addSequenceDB(). This set itself 166 * is not part of the state of this object (i.e. modifying the set 167 * does not modify this object) but the SequenceDB objects contained 168 * in the set are the same objects managed by this object. 169 */ 170 public synchronized Set getSequenceDBs() 171 { 172 Set allDBs = new HashSet(); 173 allDBs.addAll(this.sequenceDBByIdentifier.values()); 174 175 return allDBs; 176 } 177 178 /** 179 * If the given identifier is known to this sequence db installation 180 * because it has been used in a call to addSequenceDB(), then this 181 * method returns the SequenceDB associated with this 182 * identifier. Otherwise, null is returned. 183 */ 184 public synchronized SequenceDBLite getSequenceDB(String identifier) 185 { 186 if (identifier == null) { 187 throw new IllegalArgumentException("identifier was null"); 188 } 189 190 return (SequenceDBLite) this.sequenceDBByIdentifier.get(identifier); 191 } 192 193 public String toString() 194 { 195 return "SimpleSequenceDBInstallation: " 196 + this.sequenceDBByIdentifier.values(); 197 } 198 199 public synchronized boolean equals(Object o) 200 { 201 if (o == this) return true; 202 203 // if this class is a direct sub-class of Object: 204 if (o == null) return false; 205 if (! o.getClass().equals(this.getClass())) return false; 206 207 SimpleSequenceDBInstallation that = (SimpleSequenceDBInstallation) o; 208 209 // only compare fields of this class (not of super-classes): 210 if (! ObjectUtil.equals(this.sequenceDBByIdentifier, 211 that.sequenceDBByIdentifier)) return false; 212 213 // this and that are identical if we made it 'til here 214 return true; 215 } 216 217 public synchronized int hashCode() 218 { 219 // if this class is a direct sub-class of Object: 220 int hc = 0; 221 222 // only take into account fields of this class (not of super-class): 223 hc = ObjectUtil.hashCode(hc, sequenceDBByIdentifier); 224 225 return hc; 226 } 227 228 /** 229 * Test this class 230 */ 231 public static void main(String[] args) 232 { 233 System.out.println("Create sequence db installation"); 234 SimpleSequenceDBInstallation dbInst = new SimpleSequenceDBInstallation(); 235 System.out.println("Sequence db installation serves " + dbInst.getSequenceDBs().size() + " sequence dbs"); 236 System.out.println("add swissprot (aka sprot, sp) and genbank (aka gb) do sequence db installation"); 237 Set swissprotIDs = new HashSet(); 238 swissprotIDs.add("sprot"); 239 swissprotIDs.add("sp"); 240 dbInst.addSequenceDB("swissprot", swissprotIDs); 241 Set genbankIDs = new HashSet(); 242 genbankIDs.add("gb"); 243 genbankIDs.add("genbank"); // this is not correct but should be ignored 244 dbInst.addSequenceDB("genbank", genbankIDs); 245 System.out.println("Sequence db installation serves " + dbInst.getSequenceDBs().size() + " sequence dbs"); 246 System.out.println("Sequence db associated with identifier \"sprot\" is: " + dbInst.getSequenceDB("sprot")); 247 System.out.println("Sequence db associated with identifier \"swissprot\" is: " + dbInst.getSequenceDB("swissprot")); 248 System.out.println("Sequence db associated with identifier \"sp\" is: " + dbInst.getSequenceDB("sp")); 249 System.out.println("Sequence db associated with identifier \"willi\" is: " + dbInst.getSequenceDB("willi")); 250 System.out.println("Sequence db associated with identifier \"gb\" is: " + dbInst.getSequenceDB("gb")); 251 System.out.println("Sequence db associated with identifier \"genbank\" is: " + dbInst.getSequenceDB("genbank")); 252 System.out.println("Sequence db associated with identifier \"genebank\" is: " + dbInst.getSequenceDB("genebank")); 253 } 254}