/dependencies/jaudiotagger/src/main/java/org/jaudiotagger/audio/generic/AbstractTag.java
Java | 421 lines | 180 code | 53 blank | 188 comment | 33 complexity | e3c2f110254fba65c227a2350b2588a9 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, BSD-3-Clause
- /*
- * jaudiotagger library
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- package org.jaudiotagger.audio.generic;
-
- import org.jaudiotagger.tag.*;
- import org.jaudiotagger.tag.datatype.Artwork;
-
- import java.util.*;
-
- /**
- * This class is the default implementation for
- * {@link org.jaudiotagger.tag.Tag} and introduces some more useful
- * functionality to be implemented.<br>
- *
- * @author Raphaƫl Slinckx
- */
- public abstract class AbstractTag implements Tag {
- /**
- * Stores the amount of {@link TagField} with {@link TagField#isCommon()}
- * <code>true</code>.
- */
- protected int commonNumber = 0;
-
- /**
- * This map stores the {@linkplain TagField#getId() ids} of the stored
- * fields to the {@linkplain TagField fields} themselves. Because a linked hashMap is used the order
- * that they are added in is preserved, the only exception to this rule is when two fields of the same id
- * exist, both will be returned according to when the first item was added to the file. <br>
- */
- protected Map<String, List<TagField>> fields = new LinkedHashMap<String, List<TagField>>();
-
- /**
- * Add field
- *
- * @see org.jaudiotagger.tag.Tag#addField(org.jaudiotagger.tag.TagField)
- * <p/>
- * Changed so add empty fields
- */
- public void addField(TagField field) {
- if (field == null) {
- return;
- }
-
- List<TagField> list = fields.get(field.getId());
-
- // There was no previous item
- if (list == null) {
- list = new ArrayList<TagField>();
- list.add(field);
- fields.put(field.getId(), list);
- if (field.isCommon()) {
- commonNumber++;
- }
- } else {
- // We append to existing list
- list.add(field);
- }
- }
-
-
- /**
- * Get list of fields within this tag with the specified id
- *
- * @see org.jaudiotagger.tag.Tag#getFields(java.lang.String)
- */
- public List<TagField> getFields(String id) {
- List<TagField> list = fields.get(id);
-
- if (list == null) {
- return new ArrayList<TagField>();
- }
-
- return list;
- }
-
- /**
- * @param id
- * @return
- */
-
- //Needs to be overridden
- //TODO remove
- public List<TagField> getFields(FieldKey id) throws KeyNotFoundException {
- List<TagField> list = fields.get(id.name());
- if (list == null) {
- return new ArrayList<TagField>();
- }
- return list;
- }
-
-
- /**
- * @param id
- * @param index
- * @return
- */
- public String getItem(String id, int index) {
- List<TagField> l = getFields(id);
- return (l.size() > index) ? l.get(index).toString() : "";
- }
-
- /**
- * Retrieve the first value that exists for this generic key
- *
- * @param genericKey
- * @return
- */
- public String getFirst(FieldKey genericKey) throws KeyNotFoundException {
- return getValue(genericKey, 0);
- }
-
- /**
- * @param id
- * @return
- */
- public String getFirst(String id) {
- List<TagField> l = getFields(id);
- return (l.size() != 0) ? l.get(0).toString() : "";
- }
-
- /**
- * @param id audio specific key
- * @return
- */
- public TagField getFirstField(String id) {
- List<TagField> l = getFields(id);
- return (l.size() != 0) ? l.get(0) : null;
- }
-
-
- /**
- * @see org.jaudiotagger.tag.Tag#getFields()
- */
- public Iterator<TagField> getFields() {
- final Iterator<Map.Entry<String, List<TagField>>> it = this.fields.entrySet().iterator();
- return new Iterator<TagField>() {
- private Iterator<TagField> fieldsIt;
-
- private void changeIt() {
- if (!it.hasNext()) {
- return;
- }
-
- Map.Entry<String, List<TagField>> e = it.next();
- List<TagField> l = e.getValue();
- fieldsIt = l.iterator();
- }
-
- public boolean hasNext() {
- if (fieldsIt == null) {
- changeIt();
- }
- return it.hasNext() || (fieldsIt != null && fieldsIt.hasNext());
- }
-
- public TagField next() {
- if (!fieldsIt.hasNext()) {
- changeIt();
- }
-
- return fieldsIt.next();
- }
-
- public void remove() {
- fieldsIt.remove();
- }
- };
- }
-
- /**
- * Return field count
- * <p/>
- * TODO:There must be a more efficient way to do this.
- *
- * @return field count
- */
- public int getFieldCount() {
- Iterator it = getFields();
- int count = 0;
- while (it.hasNext()) {
- count++;
- it.next();
- }
- return count;
- }
-
- public int getFieldCountIncludingSubValues() {
- return getFieldCount();
- }
-
- /**
- * Does this tag contain any comon fields
- *
- * @see org.jaudiotagger.tag.Tag#hasCommonFields()
- */
- public boolean hasCommonFields() {
- return commonNumber != 0;
- }
-
- /**
- * Does this tag contain a field with the specified id
- *
- * @see org.jaudiotagger.tag.Tag#hasField(java.lang.String)
- */
- public boolean hasField(String id) {
- return getFields(id).size() != 0;
- }
-
- /**
- * Determines whether the given charset encoding may be used for the
- * represented tagging system.
- *
- * @param enc charset encoding.
- * @return <code>true</code> if the given encoding can be used.
- */
- protected abstract boolean isAllowedEncoding(String enc);
-
- /**
- * Is this tag empty
- *
- * @see org.jaudiotagger.tag.Tag#isEmpty()
- */
- public boolean isEmpty() {
- return fields.size() == 0;
- }
-
- /**
- * Create new field and set it in the tag
- *
- * @param genericKey
- * @param value
- * @throws KeyNotFoundException
- * @throws FieldDataInvalidException
- */
- public void setField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException {
- TagField tagfield = createField(genericKey, value);
- setField(tagfield);
- }
-
-
- /**
- * Create new field and add it to the tag
- *
- * @param genericKey
- * @param value
- * @throws KeyNotFoundException
- * @throws FieldDataInvalidException
- */
- public void addField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException {
- TagField tagfield = createField(genericKey, value);
- addField(tagfield);
- }
-
- /**
- * Set field
- * <p/>
- * Changed:Just because field is empty it doesn't mean it should be deleted. That should be the choice
- * of the developer. (Or does this break things)
- *
- * @see org.jaudiotagger.tag.Tag#setField(org.jaudiotagger.tag.TagField)
- */
- public void setField(TagField field) {
- if (field == null) {
- return;
- }
-
- // If there is already an existing field with same id
- // and both are TextFields, we replace the first element
- List<TagField> list = fields.get(field.getId());
- if (list != null) {
- list.set(0, field);
- return;
- }
-
- // Else we put the new field in the fields.
- list = new ArrayList<TagField>();
- list.add(field);
- fields.put(field.getId(), list);
- if (field.isCommon()) {
- commonNumber++;
- }
- }
-
- /**
- * The m parameter is effectively ignored
- *
- * @param id
- * @param n
- * @param m
- * @return
- */
- public String getSubValue(FieldKey id, int n, int m) {
- return getValue(id, n);
- }
-
- /**
- * Set or add encoding
- *
- * @see org.jaudiotagger.tag.Tag#setEncoding(java.lang.String)
- */
- public boolean setEncoding(String enc) {
- if (!isAllowedEncoding(enc)) {
- return false;
- }
-
- Iterator it = getFields();
- while (it.hasNext()) {
- TagField field = (TagField) it.next();
- if (field instanceof TagTextField) {
- ((TagTextField) field).setEncoding(enc);
- }
- }
-
- return true;
- }
-
- /**
- * (overridden)
- *
- * @see java.lang.Object#toString()
- */
- public String toString() {
- StringBuffer out = new StringBuffer();
- out.append("Tag content:\n");
- Iterator it = getFields();
- while (it.hasNext()) {
- TagField field = (TagField) it.next();
- out.append("\t");
- out.append(field.getId());
- out.append(":");
- out.append(field.toString());
- out.append("\n");
- }
- return out.toString().substring(0, out.length() - 1);
- }
-
- /**
- * @param genericKey
- * @param value
- * @return
- * @throws KeyNotFoundException
- * @throws FieldDataInvalidException
- */
- public abstract TagField createField(FieldKey genericKey, String value) throws KeyNotFoundException, FieldDataInvalidException;
-
- /**
- * @param genericKey
- * @return
- * @throws KeyNotFoundException
- */
- public abstract TagField getFirstField(FieldKey genericKey) throws KeyNotFoundException;
-
- /**
- * @param fieldKey
- * @throws KeyNotFoundException
- */
- public abstract void deleteField(FieldKey fieldKey) throws KeyNotFoundException;
-
-
- /**
- * Delete all occurrences of field with this id.
- *
- * @param key
- */
- public void deleteField(String key) {
- fields.remove(key);
- }
-
- public Artwork getFirstArtwork() {
- List<Artwork> artwork = getArtworkList();
- if (artwork.size() > 0) {
- return artwork.get(0);
- }
- return null;
- }
-
- /**
- * Create field and then set within tag itself
- *
- * @param artwork
- * @throws FieldDataInvalidException
- */
- public void setField(Artwork artwork) throws FieldDataInvalidException {
- this.setField(createField(artwork));
- }
-
- /**
- * Create field and then add within tag itself
- *
- * @param artwork
- * @throws FieldDataInvalidException
- */
- public void addField(Artwork artwork) throws FieldDataInvalidException {
- this.addField(createField(artwork));
- }
-
-
- /**
- * Delete all instance of artwork Field
- *
- * @throws KeyNotFoundException
- */
- public void deleteArtworkField() throws KeyNotFoundException {
- this.deleteField(FieldKey.COVER_ART);
- }
- }