1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package entagged.audioformats.generic;
20
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26
27 import entagged.audioformats.Tag;
28
29 /***
30 * This class is the default implementation for
31 * {@link entagged.audioformats.Tag} and introduces some more useful
32 * functionality to be implemented.<br>
33 *
34 * @author Raphaël Slinckx
35 */
36 public abstract class AbstractTag implements Tag {
37
38 /***
39 * Stores the amount of {@link TagField} with {@link TagField#isCommon()}
40 * <code>true</code>.
41 */
42 protected int commonNumber = 0;
43
44 /***
45 * This map stores the {@linkplain TagField#getId() ids} of the stored
46 * fields to the {@linkplain TagField fields} themselves.<br>
47 */
48 protected HashMap fields = new HashMap();
49
50 /***
51 * (overridden) The use of this method is not recommended. One must know the
52 * underlying audio files implementation.
53 *
54 * @see entagged.audioformats.Tag#add(entagged.audioformats.generic.TagField)
55 */
56 /***
57 * (overridden)
58 *
59 * @see entagged.audioformats.Tag#add(entagged.audioformats.generic.TagField)
60 */
61 public void add(TagField field) {
62 if (field == null || field.isEmpty())
63 return;
64
65 List list = (List) fields.get(field.getId());
66
67
68 if (list == null) {
69 list = new ArrayList();
70 list.add(field);
71 fields.put(field.getId(), list);
72 if (field.isCommon())
73 commonNumber++;
74 } else {
75
76 list.add(field);
77 }
78 }
79
80 /***
81 * (overridden)
82 *
83 * @see entagged.audioformats.Tag#addAlbum(java.lang.String)
84 */
85 public void addAlbum(String s) {
86 add(createAlbumField(s));
87 }
88
89 /***
90 * (overridden)
91 *
92 * @see entagged.audioformats.Tag#addArtist(java.lang.String)
93 */
94 public void addArtist(String s) {
95 add(createArtistField(s));
96 }
97
98 /***
99 * (overridden)
100 *
101 * @see entagged.audioformats.Tag#addComment(java.lang.String)
102 */
103 public void addComment(String s) {
104 add(createCommentField(s));
105 }
106
107 /***
108 * (overridden)
109 *
110 * @see entagged.audioformats.Tag#addGenre(java.lang.String)
111 */
112 public void addGenre(String s) {
113 add(createGenreField(s));
114 }
115
116 /***
117 * (overridden)
118 *
119 * @see entagged.audioformats.Tag#addTitle(java.lang.String)
120 */
121 public void addTitle(String s) {
122 add(createTitleField(s));
123 }
124
125 /***
126 * (overridden)
127 *
128 * @see entagged.audioformats.Tag#addTrack(java.lang.String)
129 */
130 public void addTrack(String s) {
131 add(createTrackField(s));
132 }
133
134 /***
135 * (overridden)
136 *
137 * @see entagged.audioformats.Tag#addYear(java.lang.String)
138 */
139 public void addYear(String s) {
140 add(createYearField(s));
141 }
142
143 /***
144 * Creates a field which represents the "album".<br>
145 * The field will already contain the given content.
146 *
147 * @param content
148 * The content of the created field.
149 * @return tagfield representing the "album"
150 */
151 protected abstract TagField createAlbumField(String content);
152
153 /***
154 * Creates a field which represents the "artist".<br>
155 * The field will already contain the given content.
156 *
157 * @param content
158 * The content of the created field.
159 * @return tagfield representing the "artist"
160 */
161 protected abstract TagField createArtistField(String content);
162
163 /***
164 * Creates a field which represents the "comment".<br>
165 * The field will already contain the given content.
166 *
167 * @param content
168 * The content of the created field.
169 * @return tagfield representing the "comment"
170 */
171 protected abstract TagField createCommentField(String content);
172
173 /***
174 * Creates a field which represents the "genre".<br>
175 * The field will already contain the given content.
176 *
177 * @param content
178 * The content of the created field.
179 * @return tagfield representing the "genre"
180 */
181 protected abstract TagField createGenreField(String content);
182
183 /***
184 * Creates a field which represents the "title".<br>
185 * The field will already contain the given content.
186 *
187 * @param content
188 * The content of the created field.
189 * @return tagfield representing the "title"
190 */
191 protected abstract TagField createTitleField(String content);
192
193 /***
194 * Creates a field which represents the "track".<br>
195 * The field will already contain the given content.
196 *
197 * @param content
198 * The content of the created field.
199 * @return tagfield representing the "track"
200 */
201 protected abstract TagField createTrackField(String content);
202
203 /***
204 * Creates a field which represents the "year".<br>
205 * The field will already contain the given content.
206 *
207 * @param content
208 * The content of the created field.
209 * @return tagfield representing the "year"
210 */
211 protected abstract TagField createYearField(String content);
212
213 /***
214 * (overridden)
215 *
216 * @see entagged.audioformats.Tag#get(java.lang.String)
217 */
218 public List get(String id) {
219 List list = (List) fields.get(id);
220
221 if (list == null)
222 return new ArrayList();
223
224 return list;
225 }
226
227 /***
228 * (overridden)
229 *
230 * @see entagged.audioformats.Tag#getAlbum()
231 */
232 public List getAlbum() {
233 return get(getAlbumId());
234 }
235
236 /***
237 * Returns the identifier for a field representing the "album"<br>
238 *
239 * @see TagField#getId()
240 * @return identifier for the "album" field.
241 */
242 protected abstract String getAlbumId();
243
244 /***
245 * (overridden)
246 *
247 * @see entagged.audioformats.Tag#getArtist()
248 */
249 public List getArtist() {
250 return get(getArtistId());
251 }
252
253 /***
254 * Returns the identifier for a field representing the "artist"<br>
255 *
256 * @see TagField#getId()
257 * @return identifier for the "artist" field.
258 */
259 protected abstract String getArtistId();
260
261 /***
262 * (overridden)
263 *
264 * @see entagged.audioformats.Tag#getComment()
265 */
266 public List getComment() {
267 return get(getCommentId());
268 }
269
270 /***
271 * Returns the identifier for a field representing the "comment"<br>
272 *
273 * @see TagField#getId()
274 * @return identifier for the "comment" field.
275 */
276 protected abstract String getCommentId();
277
278 /***
279 * (overridden)
280 *
281 * @see entagged.audioformats.Tag#getFields()
282 */
283 public Iterator getFields() {
284 final Iterator it = this.fields.entrySet().iterator();
285 return new Iterator() {
286 private Iterator fieldsIt;
287
288 private void changeIt() {
289 if (!it.hasNext())
290 return;
291
292 List l = (List) ((Map.Entry) it.next()).getValue();
293 fieldsIt = l.iterator();
294 }
295
296 public boolean hasNext() {
297 if (fieldsIt == null) {
298 changeIt();
299 }
300 return it.hasNext() || (fieldsIt != null && fieldsIt.hasNext());
301 }
302
303 public Object next() {
304 if (!fieldsIt.hasNext())
305 changeIt();
306
307 return fieldsIt.next();
308 }
309
310 public void remove() {
311 fieldsIt.remove();
312 }
313 };
314 }
315
316 /***
317 * (overridden)
318 *
319 * @see entagged.audioformats.Tag#getFirstAlbum()
320 */
321 public String getFirstAlbum() {
322 List l = get(getAlbumId());
323 return (l.size() != 0) ? ((TagTextField) l.get(0)).getContent() : "";
324 }
325
326 /***
327 * (overridden)
328 *
329 * @see entagged.audioformats.Tag#getFirstArtist()
330 */
331 public String getFirstArtist() {
332 List l = get(getArtistId());
333 return (l.size() != 0) ? ((TagTextField) l.get(0)).getContent() : "";
334 }
335
336 /***
337 * (overridden)
338 *
339 * @see entagged.audioformats.Tag#getFirstComment()
340 */
341 public String getFirstComment() {
342 List l = get(getCommentId());
343 return (l.size() != 0) ? ((TagTextField) l.get(0)).getContent() : "";
344 }
345
346 /***
347 * (overridden)
348 *
349 * @see entagged.audioformats.Tag#getFirstGenre()
350 */
351 public String getFirstGenre() {
352 List l = get(getGenreId());
353 return (l.size() != 0) ? ((TagTextField) l.get(0)).getContent() : "";
354 }
355
356 /***
357 * (overridden)
358 *
359 * @see entagged.audioformats.Tag#getFirstTitle()
360 */
361 public String getFirstTitle() {
362 List l = get(getTitleId());
363 return (l.size() != 0) ? ((TagTextField) l.get(0)).getContent() : "";
364 }
365
366 /***
367 * (overridden)
368 *
369 * @see entagged.audioformats.Tag#getFirstTrack()
370 */
371 public String getFirstTrack() {
372 List l = get(getTrackId());
373 return (l.size() != 0) ? ((TagTextField) l.get(0)).getContent() : "";
374 }
375
376 /***
377 * (overridden)
378 *
379 * @see entagged.audioformats.Tag#getFirstYear()
380 */
381 public String getFirstYear() {
382 List l = get(getYearId());
383 return (l.size() != 0) ? ((TagTextField) l.get(0)).getContent() : "";
384 }
385
386 /***
387 * (overridden)
388 *
389 * @see entagged.audioformats.Tag#getGenre()
390 */
391 public List getGenre() {
392 return get(getGenreId());
393 }
394
395 /***
396 * Returns the identifier for a field representing the "genre"<br>
397 *
398 * @see TagField#getId()
399 * @return identifier for the "genre" field.
400 */
401 protected abstract String getGenreId();
402
403 /***
404 * (overridden)
405 *
406 * @see entagged.audioformats.Tag#getTitle()
407 */
408 public List getTitle() {
409 return get(getTitleId());
410 }
411
412 /***
413 * Returns the identifier for a field representing the "title"<br>
414 *
415 * @see TagField#getId()
416 * @return identifier for the "title" field.
417 */
418 protected abstract String getTitleId();
419
420 /***
421 * (overridden)
422 *
423 * @see entagged.audioformats.Tag#getTrack()
424 */
425 public List getTrack() {
426 return get(getTrackId());
427 }
428
429 /***
430 * Returns the identifier for a field representing the "track"<br>
431 *
432 * @see TagField#getId()
433 * @return identifier for the "track" field.
434 */
435 protected abstract String getTrackId();
436
437 /***
438 * (overridden)
439 *
440 * @see entagged.audioformats.Tag#getYear()
441 */
442 public List getYear() {
443 return get(getYearId());
444 }
445
446 /***
447 * Returns the identifier for a field representing the "year"<br>
448 *
449 * @see TagField#getId()
450 * @return identifier for the "year" field.
451 */
452 protected abstract String getYearId();
453
454 /***
455 * (overridden)
456 *
457 * @see entagged.audioformats.Tag#hasCommonFields()
458 */
459 public boolean hasCommonFields() {
460 return commonNumber != 0;
461 }
462
463 /***
464 * (overridden)
465 *
466 * @see entagged.audioformats.Tag#hasField(java.lang.String)
467 */
468 public boolean hasField(String id) {
469 return get(id).size() != 0;
470 }
471
472 /***
473 * Determines whether the given charset encoding may be used for the
474 * represented tagging system.
475 *
476 * @param enc
477 * charset encoding.
478 * @return <code>true</code> if the given encoding can be used.
479 */
480 protected abstract boolean isAllowedEncoding(String enc);
481
482 /***
483 * (overridden)
484 *
485 * @see entagged.audioformats.Tag#isEmpty()
486 */
487 public boolean isEmpty() {
488 return fields.size() == 0;
489 }
490
491 /***
492 * (overridden)
493 *
494 * @see entagged.audioformats.Tag#merge(entagged.audioformats.Tag)
495 */
496 public void merge(Tag tag) {
497
498
499
500
501
502 if (getTitle().size() == 0)
503 setTitle(tag.getFirstTitle());
504 if (getArtist().size() == 0)
505 setArtist(tag.getFirstArtist());
506 if (getAlbum().size() == 0)
507 setAlbum(tag.getFirstAlbum());
508 if (getYear().size() == 0)
509 setYear(tag.getFirstYear());
510 if (getComment().size() == 0)
511 setComment(tag.getFirstComment());
512 if (getTrack().size() == 0)
513 setTrack(tag.getFirstTrack());
514 if (getGenre().size() == 0)
515 setGenre(tag.getFirstGenre());
516 }
517
518 /***
519 * (overridden)
520 *
521 * @see entagged.audioformats.Tag#set(entagged.audioformats.generic.TagField)
522 */
523 public void set(TagField field) {
524 if (field == null)
525 return;
526
527
528 if (field.isEmpty()) {
529 Object removed = fields.remove(field.getId());
530 if (removed != null && field.isCommon())
531 commonNumber--;
532 return;
533 }
534
535
536
537 List l = (List) fields.get(field.getId());
538 if (l != null) {
539 TagField f = (TagField) l.get(0);
540 f.copyContent(field);
541 return;
542 }
543
544
545 l = new ArrayList();
546 l.add(field);
547 fields.put(field.getId(), l);
548 if (field.isCommon())
549 commonNumber++;
550 }
551
552 /***
553 * (overridden)
554 *
555 * @see entagged.audioformats.Tag#setAlbum(java.lang.String)
556 */
557 public void setAlbum(String s) {
558 set(createAlbumField(s));
559 }
560
561 /***
562 * (overridden)
563 *
564 * @see entagged.audioformats.Tag#setArtist(java.lang.String)
565 */
566 public void setArtist(String s) {
567 set(createArtistField(s));
568 }
569
570 /***
571 * (overridden)
572 *
573 * @see entagged.audioformats.Tag#setComment(java.lang.String)
574 */
575 public void setComment(String s) {
576 set(createCommentField(s));
577 }
578
579 /***
580 * (overridden)
581 *
582 * @see entagged.audioformats.Tag#setEncoding(java.lang.String)
583 */
584 public boolean setEncoding(String enc) {
585 if (!isAllowedEncoding(enc)) {
586 return false;
587 }
588
589 Iterator it = getFields();
590 while (it.hasNext()) {
591 TagField field = (TagField) it.next();
592 if (field instanceof TagTextField) {
593 ((TagTextField) field).setEncoding(enc);
594 }
595 }
596
597 return true;
598 }
599
600 /***
601 * (overridden)
602 *
603 * @see entagged.audioformats.Tag#setGenre(java.lang.String)
604 */
605 public void setGenre(String s) {
606 set(createGenreField(s));
607 }
608
609 /***
610 * (overridden)
611 *
612 * @see entagged.audioformats.Tag#setTitle(java.lang.String)
613 */
614 public void setTitle(String s) {
615 set(createTitleField(s));
616 }
617
618 /***
619 * (overridden)
620 *
621 * @see entagged.audioformats.Tag#setTrack(java.lang.String)
622 */
623 public void setTrack(String s) {
624 set(createTrackField(s));
625 }
626
627 /***
628 * (overridden)
629 *
630 * @see entagged.audioformats.Tag#setYear(java.lang.String)
631 */
632 public void setYear(String s) {
633 set(createYearField(s));
634 }
635
636 /***
637 * (overridden)
638 *
639 * @see java.lang.Object#toString()
640 */
641 public String toString() {
642 StringBuffer out = new StringBuffer();
643 out.append("Tag content:\n");
644 Iterator it = getFields();
645 while (it.hasNext()) {
646 TagField field = (TagField) it.next();
647 out.append("\t");
648 out.append(field.getId());
649 out.append(" : ");
650 out.append(field.toString());
651 out.append("\n");
652 }
653 return out.toString().substring(0, out.length() - 1);
654 }
655 }