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.distributed; 023 024import java.util.HashSet; 025import java.util.Iterator; 026import java.util.Set; 027 028import org.biojava.bio.BioException; 029import org.biojava.bio.seq.Sequence; 030import org.biojava.bio.seq.db.AbstractSequenceDB; 031import org.biojava.bio.seq.db.IllegalIDException; 032import org.biojava.bio.seq.db.SequenceDB; 033import org.biojava.utils.ChangeEvent; 034import org.biojava.utils.ChangeSupport; 035import org.biojava.utils.ChangeType; 036import org.biojava.utils.ChangeVetoException; 037 038/** 039 * Sequence database from the meta-DAS system. 040 * 041 * @author Thomas Down 042 * @author Matthew Pocock 043 * @since 1.2 044 * 045 * Once you've made one of these and populated it with a few DistDataSource instances, 046 * you should be able to prety much forget about it and use it directly as a normal 047 * SequenceDB implementation. 048 * 049 * DataSources can be added and removed while the object is live. 050 */ 051 052public class DistributedSequenceDB extends AbstractSequenceDB implements SequenceDB { 053 public static final ChangeType DATASOURCE = new ChangeType( 054 "Data sources have changes in a Distributed Sequence DB", 055 "org.biojava.bio.seq.distributed.DistributedSequenceDB", 056 "DATASOURCE", 057 ChangeType.UNKNOWN 058 ); 059 060 public static final ChangeType DATASOURCE_SELECTION = new ChangeType( 061 "The set of available data sources has changes in a Distributed Sequence DB", 062 "org.biojava.bio.seq.distributed.DistributedSequenceDB", 063 "DATASOURCE_SELECTION", 064 DistributedSequenceDB.DATASOURCE 065 ); 066 067 private Set datasources; 068 private transient ChangeSupport changeSupport; 069 070 protected boolean hasChangeSupport() { 071 return (changeSupport != null); 072 } 073 074 protected ChangeSupport getChangeSupport() { 075 if (changeSupport == null) { 076 changeSupport = new ChangeSupport(); 077 } 078 return changeSupport; 079 } 080 081 { 082 datasources = new HashSet(); 083 } 084 085 /** 086 * Get the current set of all currently registered data sources. 087 * 088 * <p> 089 * The returned Set is totaly independant of any future changes made to the 090 * distributed sequence DB. 091 * </p> 092 * 093 * @return a new Set containing all DistDataSource instances registered at 094 * the time 095 */ 096 public Set getDataSources() { 097 return new HashSet(datasources); 098 } 099 100 /** 101 * Add a distributed data source. 102 * 103 * @param dds the DistDataSource to add 104 * @throws ChangeVetoException if the data source could not be added 105 */ 106 public void addDataSource(DistDataSource dds) 107 throws ChangeVetoException 108 { 109 if (datasources.contains(dds)) { 110 return; 111 } 112 113 if (hasChangeSupport()) { 114 ChangeSupport cs = getChangeSupport(); 115 synchronized (cs) { 116 ChangeEvent cev = new ChangeEvent(this, 117 DATASOURCE_SELECTION, 118 dds, 119 null); 120 cs.firePreChangeEvent(cev); 121 _addDataSource(dds); 122 cs.firePostChangeEvent(cev); 123 } 124 } else { 125 _addDataSource(dds); 126 } 127 } 128 129 private void _addDataSource(DistDataSource dds) { 130 datasources.add(dds); 131 } 132 133 /** 134 * Remove a distributed data source. 135 * 136 * @param dds the DistributedDataSource to remove 137 * @throws ChangeVetoException if the data source could not be removed 138 */ 139 public void removeDataSource(DistDataSource dds) 140 throws ChangeVetoException 141 { 142 if (!datasources.contains(dds)) { 143 throw new ChangeVetoException("That datasource isn't currently installed"); 144 } 145 146 if (hasChangeSupport()) { 147 ChangeSupport cs = getChangeSupport(); 148 synchronized (cs) { 149 ChangeEvent cev = new ChangeEvent(this, 150 DATASOURCE_SELECTION, 151 null, 152 dds); 153 cs.firePreChangeEvent(cev); 154 _removeDataSource(dds); 155 cs.firePostChangeEvent(cev); 156 } 157 } else { 158 _removeDataSource(dds); 159 } 160 } 161 162 private void _removeDataSource(DistDataSource dds) { 163 datasources.remove(dds); 164 } 165 166 public String getName() { 167 return "<unknown meta-das>"; 168 } 169 170 public void addSequence(Sequence seq) 171 throws ChangeVetoException 172 { 173 throw new ChangeVetoException("Can't add sequences to meta-das"); 174 } 175 176 public void removeSequence(String id) 177 throws ChangeVetoException 178 { 179 throw new ChangeVetoException("Can't add sequences to meta-das"); 180 } 181 182 public Sequence getSequence(String id) 183 throws IllegalIDException, BioException 184 { 185 Set featureSources = new HashSet(); 186 DistDataSource seqSource = null; 187 188 for (Iterator i = datasources.iterator(); i.hasNext(); ) { 189 DistDataSource dds = (DistDataSource) i.next(); 190 if (dds.hasSequence(id) && seqSource == null) { 191 seqSource = dds; 192 } 193 194 if (dds.hasFeatures(id)) { 195 featureSources.add(dds); 196 } 197 } 198 199 if (seqSource == null) { 200 throw new IllegalIDException("No sequence source for ID: " + id); 201 } 202 203 return new DistributedSequence(id, this, seqSource, featureSources); 204 } 205 206 public Set ids() { 207 Set ids = new HashSet(); 208 for (Iterator i = datasources.iterator(); i.hasNext(); ) { 209 DistDataSource dds = (DistDataSource) i.next(); 210 try { 211 ids.addAll(dds.ids(true)); 212 } catch (BioException ex) { 213 } 214 } 215 return ids; 216 } 217 218}