Source code: com/virtuosotechnologies/asaph/standardmodel/StdSongIDResultSet.java
1 /*
2 ================================================================================
3
4 FILE: StdSongIDResultSet.java
5
6 PROJECT:
7
8 Asaph
9
10 CONTENTS:
11
12 Standard implementation of SongIDResultSet
13
14 PROGRAMMERS:
15
16 Daniel Azuma (DA) <dazuma@kagi.com>
17
18 COPYRIGHT:
19
20 Copyright (C) 2003 Daniel Azuma (dazuma@kagi.com)
21
22 This program is free software; you can redistribute it and/or
23 modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2
25 of the License, or (at your option) any later version.
26
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public
33 License along with this program; if not, write to
34 Free Software Foundation, Inc.
35 59 Temple Place, Suite 330
36 Boston, MA 02111-1307 USA
37
38 ================================================================================
39 */
40
41
42 package com.virtuosotechnologies.asaph.standardmodel;
43
44
45 import java.util.Set;
46 import java.util.Collection;
47 import java.util.Map;
48 import java.util.LinkedHashMap;
49 import java.util.Iterator;
50
51 import com.virtuosotechnologies.asaph.model.SongIDResultSet;
52 import com.virtuosotechnologies.asaph.model.SongDatabase;
53 import com.virtuosotechnologies.asaph.model.SongID;
54 import com.virtuosotechnologies.asaph.model.Song;
55 import com.virtuosotechnologies.asaph.model.SongDatabaseFailedException;
56
57
58 /**
59 * Standard implementation of SongIDResultSet
60 */
61 /*package*/ class StdSongIDResultSet
62 implements SongIDResultSet
63 {
64 private SongDatabase database_;
65 private Map dataMap_;
66 private StdSongIDResultSet setLink_;
67
68
69 /*package*/ StdSongIDResultSet(
70 SongDatabase database)
71 {
72 database_ = database;
73 dataMap_ = new LinkedHashMap();
74 setLink_ = null;
75 }
76
77
78 /*package*/ StdSongIDResultSet(
79 StdSongIDResultSet link)
80 {
81 setLink_ = link;
82 dataMap_ = new LinkedHashMap();
83 database_ = setLink_.getDatabase();
84 synchronized(setLink_)
85 {
86 for (Iterator iter = setLink_.getEntryCollection().iterator(); iter.hasNext(); )
87 {
88 EntryImpl entry = (EntryImpl)iter.next();
89 dataMap_.put(entry.getSongID(), new EntryImpl(entry));
90 }
91 }
92 }
93
94
95 /*package*/ class EntryImpl
96 implements Entry
97 {
98 private SongID songID_;
99 private Song cachedSong_;
100 private boolean isCached_;
101 private Object data_;
102 private EntryImpl entryLink_;
103
104 /*package*/ EntryImpl(
105 SongID songID)
106 {
107 songID_ = songID;
108 entryLink_ = null;
109 cachedSong_ = null;
110 isCached_ = false;
111 data_ = null;
112 }
113
114 /*package*/ EntryImpl(
115 EntryImpl link)
116 {
117 entryLink_ = link;
118 songID_ = entryLink_.songID_;
119 synchronized(entryLink_)
120 {
121 cachedSong_ = entryLink_.cachedSong_;
122 isCached_ = entryLink_.isCached_;
123 data_ = entryLink_.data_;
124 }
125 }
126
127 /*package*/ synchronized void setCachedSong(
128 Song cachedSong)
129 {
130 cachedSong_ = cachedSong;
131 }
132
133 /*package*/ synchronized void clearCachedSong()
134 {
135 cachedSong_ = null;
136 isCached_ = false;
137 }
138
139 public SongID getSongID()
140 {
141 return songID_;
142 }
143
144 public synchronized Object getData()
145 {
146 return data_;
147 }
148
149 public synchronized void setData(
150 Object data)
151 {
152 data_ = data;
153 }
154
155 public synchronized Song getSong()
156 {
157 if (!isCached_)
158 {
159 if (setLink_ != null)
160 {
161 if (entryLink_ == null)
162 {
163 entryLink_ = (EntryImpl)setLink_.getEntryFor(songID_);
164 }
165 if (entryLink_ != null)
166 {
167 cachedSong_ = entryLink_.getSong();
168 }
169 }
170 if (cachedSong_ == null)
171 {
172 try
173 {
174 cachedSong_ = database_.checkOutSong(songID_);
175 if (entryLink_ != null)
176 {
177 entryLink_.setCachedSong(cachedSong_);
178 }
179 }
180 catch (SongDatabaseFailedException ex)
181 {
182 }
183 }
184 isCached_ = true;
185 }
186 return cachedSong_;
187 }
188 }
189
190
191 //-------------------------------------------------------------------------
192 // Methods of Set
193 //-------------------------------------------------------------------------
194
195 public synchronized int size()
196 {
197 return dataMap_.size();
198 }
199
200
201 public synchronized boolean isEmpty()
202 {
203 return dataMap_.isEmpty();
204 }
205
206
207 public synchronized boolean contains(
208 Object o)
209 {
210 return dataMap_.containsKey(o);
211 }
212
213
214 public synchronized Iterator iterator()
215 {
216 return dataMap_.keySet().iterator();
217 }
218
219
220 public synchronized Object[] toArray()
221 {
222 return dataMap_.keySet().toArray();
223 }
224
225
226 public synchronized Object[] toArray(
227 Object a[])
228 {
229 return dataMap_.keySet().toArray(a);
230 }
231
232
233 public synchronized boolean add(
234 Object o)
235 {
236 SongID songID = (SongID)o;
237 if (songID.getDatabase() != database_)
238 {
239 throw new IllegalArgumentException("Added SongID part of the wrong database");
240 }
241 if (dataMap_.get(songID) == null)
242 {
243 EntryImpl entry = null;
244 if (setLink_ != null)
245 {
246 entry = (EntryImpl)setLink_.getEntryFor(songID);
247 }
248 if (entry != null)
249 {
250 entry = new EntryImpl(entry);
251 }
252 else
253 {
254 entry = new EntryImpl(songID);
255 }
256 dataMap_.put(songID, entry);
257 return true;
258 }
259 else
260 {
261 return false;
262 }
263 }
264
265
266 public synchronized boolean remove(
267 Object o)
268 {
269 Object val = dataMap_.remove(o);
270 return val != null;
271 }
272
273
274 public synchronized boolean containsAll(
275 Collection c)
276 {
277 for (Iterator iter = c.iterator(); iter.hasNext(); )
278 {
279 if (!dataMap_.containsKey(iter.next()))
280 {
281 return false;
282 }
283 }
284 return true;
285 }
286
287
288 public synchronized boolean addAll(
289 Collection c)
290 {
291 boolean modified = false;
292 for (Iterator iter = c.iterator(); iter.hasNext(); )
293 {
294 modified |= add(iter.next());
295 }
296 return modified;
297 }
298
299
300 public synchronized boolean retainAll(
301 Collection c)
302 {
303 boolean modified = false;
304 for (Iterator iter = dataMap_.keySet().iterator(); iter.hasNext(); )
305 {
306 Object obj = iter.next();
307 if (!c.contains(obj))
308 {
309 iter.remove();
310 modified = true;
311 }
312 }
313 return modified;
314 }
315
316
317 public synchronized boolean removeAll(
318 Collection c)
319 {
320 boolean modified = false;
321 for (Iterator iter = c.iterator(); iter.hasNext(); )
322 {
323 modified |= remove(iter.next());
324 }
325 return modified;
326 }
327
328
329 public synchronized void clear()
330 {
331 dataMap_.clear();
332 }
333
334
335 //-------------------------------------------------------------------------
336 // Methods of SongIDResultSet
337 //-------------------------------------------------------------------------
338
339 /**
340 * Create a copy of this result set that is linked to this one.
341 * A linked copy shares the song cache of the original. In addition, its initial
342 * data values are the same as the data for the original; however, the data can later
343 * be changed independent of the original.
344 *
345 * @return copy of this result set
346 */
347 public synchronized SongIDResultSet createLinkedCopy()
348 {
349 return new StdSongIDResultSet(this);
350 }
351
352
353 /**
354 * Get the SongDatabase that created this result set.
355 *
356 * @return SongDatabase
357 */
358 public SongDatabase getDatabase()
359 {
360 return database_;
361 }
362
363
364 /**
365 * Get the data associated with the given SongID.
366 *
367 * @param songID SongID to query
368 * @return the entry for this songID, or null if there isn't one.
369 */
370 public synchronized Entry getEntryFor(
371 SongID songID)
372 {
373 return (Entry)dataMap_.get(songID);
374 }
375
376
377 /**
378 * Get a collection view of the entries in the set, backed by the set.
379 * Each item in the collection is an Entry object.
380 * The collection can be modified by removing elements, but not by adding.
381 *
382 * @return Collection of Entry objects
383 */
384 public synchronized Collection getEntryCollection()
385 {
386 return dataMap_.values();
387 }
388
389
390 /**
391 * Clear the song caches for all entries in the set
392 */
393 public synchronized void clearSongCache()
394 {
395 for (Iterator iter = dataMap_.values().iterator(); iter.hasNext(); )
396 {
397 EntryImpl entry = (EntryImpl)iter.next();
398 entry.clearCachedSong();
399 }
400 }
401 }