org.jaudiotagger.tag.id3
Class AbstractID3v2Tag

java.lang.Object
  extended by org.jaudiotagger.tag.id3.AbstractTagItem
      extended by org.jaudiotagger.tag.id3.AbstractTag
          extended by org.jaudiotagger.tag.id3.AbstractID3Tag
              extended by org.jaudiotagger.tag.id3.AbstractID3v2Tag
All Implemented Interfaces:
Tag
Direct Known Subclasses:
ID3v22Tag, ID3v23Tag, ID3v24Tag

public abstract class AbstractID3v2Tag
extends AbstractID3Tag
implements Tag

This is the abstract base class for all ID3v2 tags.

Version:
$Id: AbstractID3v2Tag.java,v 1.70 2009/11/12 15:42:57 paultaylor Exp $
Author:
: Paul Taylor, : Eric Farng

Nested Class Summary
(package private)  class AbstractID3v2Tag.FrameAndSubId
          This class had to be created to minimize the duplicate code in concrete subclasses of this class.
 
Field Summary
protected  int duplicateBytes
           
protected  java.lang.String duplicateFrameId
           
protected  int emptyFrameBytes
           
protected static int FIELD_TAG_FLAG_LENGTH
           
protected static int FIELD_TAG_FLAG_POS
           
protected static int FIELD_TAG_MAJOR_VERSION_LENGTH
           
protected static int FIELD_TAG_MAJOR_VERSION_POS
           
protected static int FIELD_TAG_MINOR_VERSION_LENGTH
           
protected static int FIELD_TAG_MINOR_VERSION_POS
           
protected static int FIELD_TAG_SIZE_LENGTH
           
protected static int FIELD_TAG_SIZE_POS
           
protected static int FIELD_TAGID_LENGTH
           
protected static int FIELD_TAGID_POS
           
protected  int fileReadSize
           
 java.util.HashMap frameMap
          Map of all frames for this tag
protected  int invalidFrameBytes
           
private static long MAXIMUM_WRITABLE_CHUNK_SIZE
           
static int TAG_HEADER_LENGTH
           
protected static byte[] TAG_ID
           
protected static int TAG_SIZE_INCREMENT
           
protected static java.lang.String TYPE_BODY
           
protected static java.lang.String TYPE_DUPLICATEBYTES
          Holds byte count of invalid duplicate frames
protected static java.lang.String TYPE_DUPLICATEFRAMEID
          Holds the ids of invalid duplicate frames
protected static java.lang.String TYPE_EMPTYFRAMEBYTES
          Holds byte count of empty frames
protected static java.lang.String TYPE_FILEREADSIZE
          Holds the size of the tag as reported by the tag header
protected static java.lang.String TYPE_HEADER
           
protected static java.lang.String TYPE_INVALIDFRAMEBYTES
          Holds byte count of invalid frames
 
Fields inherited from class org.jaudiotagger.tag.id3.AbstractID3Tag
logger, TAG_RELEASE
 
Fields inherited from class org.jaudiotagger.tag.id3.AbstractTag
TYPE_TAG
 
Constructor Summary
  AbstractID3v2Tag()
          Empty Constructor
protected AbstractID3v2Tag(AbstractID3v2Tag copyObject)
          This constructor is used when a tag is created as a duplicate of another tag of the same type and version.
 
Method Summary
 void addField(Artwork artwork)
          Create field and then set within tag itself
 void addField(FieldKey genericKey, java.lang.String value)
          Create the field based on the generic key and add it to the tag
 void addField(TagField field)
          Adds a field to the structure, used internally by the library

protected abstract  void addFrame(AbstractID3v2Frame frame)
           
 void adjustPadding(java.io.File file, int paddingSize, long audioStart)
          Adjust the length of the padding at the beginning of the MP3 file, this is only called when there is currently not enough space before the start of the audio to write the tag.
protected  int calculateTagSize(int tagSize, int audioStart)
          This method determines the total tag size taking into account where the audio file starts, the size of the tagging data and user options for defining how tags should shrink or grow.
protected  void copyFrameIntoMap(java.lang.String id, AbstractID3v2Frame newFrame)
           
protected  void copyFrames(AbstractID3v2Tag copyObject)
          Copy frames from another tag,
protected  void copyPrimitives(AbstractID3v2Tag copyObject)
          Copy primitives apply to all tags
 TagField createAlbumField(java.lang.String content)
           
 TagField createArtistField(java.lang.String content)
           
 TagField createCommentField(java.lang.String content)
           
 TagField createField(FieldKey genericKey, java.lang.String value)
          Create a new TagField

Only textual data supported at the moment.

abstract  AbstractID3v2Frame createFrame(java.lang.String id)
          Create Frame of correct ID3 version with the specified id
 TagField createGenreField(java.lang.String content)
           
 TagField createLinkedArtworkField(java.lang.String url)
          Create a link to artwork, this is not recommended because the link may be broken if the mp3 or image file is moved
 void createStructure()
           
 void createStructureBody()
           
 void createStructureHeader()
           
 TagField createTitleField(java.lang.String content)
           
 TagField createTrackField(java.lang.String content)
           
 TagField createYearField(java.lang.String content)
           
 void delete(java.io.RandomAccessFile file)
          Delete Tag
 void deleteArtworkField()
          Delete all instance of artwork Field
 void deleteField(FieldKey genericKey)
          Delete fields with this generic key
protected  TagField doCreateTagField(AbstractID3v2Tag.FrameAndSubId formatKey, java.lang.String value)
          Create Frame for Id3 Key

Only textual data supported at the moment, should only be used with frames that support a simple string argument.

protected  void doDeleteTagField(AbstractID3v2Tag.FrameAndSubId formatKey)
          Internal delete method
protected  java.lang.String doGetFirst(AbstractID3v2Tag.FrameAndSubId formatKey)
           
 boolean equals(java.lang.Object obj)
          Is this tag equivalent to another
 java.util.List<TagField> get(java.lang.String id)
          Retrieve the values that exists for this id3 frame id
protected abstract  java.lang.String getAlbumId()
           
protected abstract  java.lang.String getArtistId()
           
protected abstract  java.lang.String getCommentId()
           
 int getDuplicateBytes()
          Returns the number of bytes which come from duplicate frames
 java.lang.String getDuplicateFrameId()
          Return the string which holds the ids of all duplicate frames.
 int getEmptyFrameBytes()
          Returns the number of bytes which come from empty frames
 int getFieldCount()
          Return the number of fields

 java.util.Iterator<TagField> getFields()
          Iterator over all the fields within the tag, handle multiple fields with the same id
 java.util.List<TagField> getFields(FieldKey genericKey)
          Get field(s) for this key
protected  java.nio.channels.FileLock getFileLockForWriting(java.nio.channels.FileChannel fileChannel, java.lang.String filePath)
          Get file lock for writing too file

TODO:this appears to have little effect on Windows Vista

 int getFileReadBytes()
          Returns the tag size as reported by the tag header
 java.lang.String getFirst(FieldKey genericKey)
          Retrieve the first value that exists for this generic key
 java.lang.String getFirst(java.lang.String identifier)
          Retrieve the first value that exists for this identifier

If the value is a String it returns that, otherwise returns a summary of the fields information

 Artwork getFirstArtwork()
           
 TagField getFirstField(FieldKey genericKey)
           
 AbstractID3v2Frame getFirstField(java.lang.String identifier)
          Retrieve the first tagfield that exists for this identifier
 java.lang.String getFirstGenre()
           
 java.lang.String getFirstTitle()
           
 java.lang.String getFirstTrack()
           
 java.lang.String getFirstYear()
           
 java.lang.Object getFrame(java.lang.String identifier)
          For single frames return the frame in this tag with given identifier if it exists, if multiple frames exist with the same identifier it will return a list containing all the frames with this identifier

Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body but happens to have an identifier that is valid for another version of the tag it will be returned.

protected abstract  AbstractID3v2Tag.FrameAndSubId getFrameAndSubIdFromGenericKey(FieldKey genericKey)
           
 int getFrameCount()
          Return the number of frames in this tag of a particular type, multiple frames of the same time will only be counted once
 java.util.Iterator getFrameOfType(java.lang.String identifier)
          Return all frames which start with the identifier, this can be more than one which is useful if trying to retrieve similar frames e.g TIT1,TIT2,TIT3 ...
protected abstract  java.lang.String getGenreId()
           
protected abstract  ID3Frames getID3Frames()
           
 int getInvalidFrameBytes()
          Return byte count of invalid frames
abstract  java.util.Comparator getPreferredFrameOrderComparator()
           
 int getSize()
          Return tag size based upon the sizes of the tags rather than the physical no of bytes between start of ID3Tag and start of Audio Data.Should be extended by subclasses to include header.
protected abstract  java.lang.String getTitleId()
           
protected abstract  java.lang.String getTrackId()
           
static long getV2TagSizeIfExists(java.io.File file)
          Checks to see if the file contains an ID3tag and if so return its size as reported in the tag header and return the size of the tag (including header), if no such tag exists return zero.
protected abstract  java.lang.String getYearId()
           
 boolean hasCommonFields()
          Returns true, if at least one of the contained fields is a common field (TagField.isCommon()).
 boolean hasField(java.lang.String id)
          Does this tag contain a field with the specified id
 boolean hasFrame(java.lang.String identifier)
          Return whether tag has frame with this identifier

Warning the match is only done against the identifier so if a tag contains a frame with an unsuported body but happens to have an identifier that is valid for another version of the tag it will return true

 boolean hasFrameAndBody(java.lang.String identifier)
          Return whether tag has frame with this identifier and a related body.
 boolean hasFrameOfType(java.lang.String identifier)
          Return whether tag has frame starting with this identifier

Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body but happens to have an identifier that is valid for another version of the tag it will return true

 boolean isEmpty()
          Is this tag empty
 java.util.Iterator iterator()
          Return the frames in the order they were added
protected  void loadFrameIntoMap(java.lang.String frameId, AbstractID3v2Frame next)
          Decides what to with the frame that has just be read from file.
 void mergeDuplicateFrames(AbstractID3v2Frame newFrame, java.util.List<AbstractID3v2Frame> frames)
          Add frame taking into account existing frame sof the same type
 void removeFrame(java.lang.String identifier)
          Remove frame(s) with this identifier from tag
 void removeFrameOfType(java.lang.String identifier)
          Remove any frames starting with this identifier from tag
 void removeUnsupportedFrames()
          Remove all frame(s) which have an unsupported body, in other words remove all frames that are not part of the standard frameset for this tag
private  void replaceFile(java.io.File originalFile, java.io.File newFile)
          Replace originalFile with the contents of newFile

Both files must exist in the same folder so that there are no problems with fileystem mount points

 boolean seek(java.nio.ByteBuffer byteBuffer)
          Does a tag of the correct version exist in this file.
 boolean setEncoding(java.lang.String enc)
           
 void setField(Artwork artwork)
          Create field and then set within tag itself
 void setField(FieldKey genericKey, java.lang.String value)
          Create the field based on the generic key and set it in the tag
 void setField(TagField field)
          Sets a field in the structure, used internally by the library

 void setFrame(AbstractID3v2Frame frame)
          Add a frame to this tag
 void setFrame(java.lang.String identifier, java.util.List<AbstractID3v2Frame> multiFrame)
          Used for setting multiple frames for a single frame Identifier

Warning if frame(s) already exists for this identifier thay are overwritten

TODO needs to ensure do not add an invalid frame for this tag

 void write(java.io.File file, long audioStartByte)
          Write tag to file.
 void write(java.io.RandomAccessFile file)
          Write tag to file.
 void write(java.nio.channels.WritableByteChannel channel)
          Write tag to channel.
protected  void writeBufferToFile(java.io.File file, java.nio.ByteBuffer headerBuffer, byte[] bodyByteBuffer, int padding, int sizeIncPadding, long audioStartLocation)
          Write the data from the buffer to the file
protected  java.io.ByteArrayOutputStream writeFramesToBuffer()
          Write all the frames to the byteArrayOutputStream

 
Methods inherited from class org.jaudiotagger.tag.id3.AbstractID3Tag
getIdentifier, getLoggingFilename, getMajorVersion, getRelease, getRevision, setLoggingFilename, toString
 
Methods inherited from class org.jaudiotagger.tag.id3.AbstractTagItem
isSubsetOf, read
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface org.jaudiotagger.tag.Tag
createField, getArtworkList, toString
 

Field Detail

TYPE_HEADER

protected static final java.lang.String TYPE_HEADER
See Also:
Constant Field Values

TYPE_BODY

protected static final java.lang.String TYPE_BODY
See Also:
Constant Field Values

TAG_ID

protected static final byte[] TAG_ID

TAG_HEADER_LENGTH

public static final int TAG_HEADER_LENGTH
See Also:
Constant Field Values

FIELD_TAGID_LENGTH

protected static final int FIELD_TAGID_LENGTH
See Also:
Constant Field Values

FIELD_TAG_MAJOR_VERSION_LENGTH

protected static final int FIELD_TAG_MAJOR_VERSION_LENGTH
See Also:
Constant Field Values

FIELD_TAG_MINOR_VERSION_LENGTH

protected static final int FIELD_TAG_MINOR_VERSION_LENGTH
See Also:
Constant Field Values

FIELD_TAG_FLAG_LENGTH

protected static final int FIELD_TAG_FLAG_LENGTH
See Also:
Constant Field Values

FIELD_TAG_SIZE_LENGTH

protected static final int FIELD_TAG_SIZE_LENGTH
See Also:
Constant Field Values

FIELD_TAGID_POS

protected static final int FIELD_TAGID_POS
See Also:
Constant Field Values

FIELD_TAG_MAJOR_VERSION_POS

protected static final int FIELD_TAG_MAJOR_VERSION_POS
See Also:
Constant Field Values

FIELD_TAG_MINOR_VERSION_POS

protected static final int FIELD_TAG_MINOR_VERSION_POS
See Also:
Constant Field Values

FIELD_TAG_FLAG_POS

protected static final int FIELD_TAG_FLAG_POS
See Also:
Constant Field Values

FIELD_TAG_SIZE_POS

protected static final int FIELD_TAG_SIZE_POS
See Also:
Constant Field Values

TAG_SIZE_INCREMENT

protected static final int TAG_SIZE_INCREMENT
See Also:
Constant Field Values

MAXIMUM_WRITABLE_CHUNK_SIZE

private static final long MAXIMUM_WRITABLE_CHUNK_SIZE
See Also:
Constant Field Values

frameMap

public java.util.HashMap frameMap
Map of all frames for this tag


TYPE_DUPLICATEFRAMEID

protected static final java.lang.String TYPE_DUPLICATEFRAMEID
Holds the ids of invalid duplicate frames

See Also:
Constant Field Values

duplicateFrameId

protected java.lang.String duplicateFrameId

TYPE_DUPLICATEBYTES

protected static final java.lang.String TYPE_DUPLICATEBYTES
Holds byte count of invalid duplicate frames

See Also:
Constant Field Values

duplicateBytes

protected int duplicateBytes

TYPE_EMPTYFRAMEBYTES

protected static final java.lang.String TYPE_EMPTYFRAMEBYTES
Holds byte count of empty frames

See Also:
Constant Field Values

emptyFrameBytes

protected int emptyFrameBytes

TYPE_FILEREADSIZE

protected static final java.lang.String TYPE_FILEREADSIZE
Holds the size of the tag as reported by the tag header

See Also:
Constant Field Values

fileReadSize

protected int fileReadSize

TYPE_INVALIDFRAMEBYTES

protected static final java.lang.String TYPE_INVALIDFRAMEBYTES
Holds byte count of invalid frames

See Also:
Constant Field Values

invalidFrameBytes

protected int invalidFrameBytes
Constructor Detail

AbstractID3v2Tag

public AbstractID3v2Tag()
Empty Constructor


AbstractID3v2Tag

protected AbstractID3v2Tag(AbstractID3v2Tag copyObject)
This constructor is used when a tag is created as a duplicate of another tag of the same type and version.

Parameters:
copyObject -
Method Detail

copyPrimitives

protected void copyPrimitives(AbstractID3v2Tag copyObject)
Copy primitives apply to all tags

Parameters:
copyObject -

copyFrames

protected void copyFrames(AbstractID3v2Tag copyObject)
Copy frames from another tag,

Parameters:
copyObject -

addFrame

protected abstract void addFrame(AbstractID3v2Frame frame)

getDuplicateBytes

public int getDuplicateBytes()
Returns the number of bytes which come from duplicate frames

Returns:
the number of bytes which come from duplicate frames

getDuplicateFrameId

public java.lang.String getDuplicateFrameId()
Return the string which holds the ids of all duplicate frames.

Returns:
the string which holds the ids of all duplicate frames.

getEmptyFrameBytes

public int getEmptyFrameBytes()
Returns the number of bytes which come from empty frames

Returns:
the number of bytes which come from empty frames

getInvalidFrameBytes

public int getInvalidFrameBytes()
Return byte count of invalid frames

Returns:
byte count of invalid frames

getFileReadBytes

public int getFileReadBytes()
Returns the tag size as reported by the tag header

Returns:
the tag size as reported by the tag header

hasFrame

public boolean hasFrame(java.lang.String identifier)
Return whether tag has frame with this identifier

Warning the match is only done against the identifier so if a tag contains a frame with an unsuported body but happens to have an identifier that is valid for another version of the tag it will return true

Parameters:
identifier - frameId to lookup
Returns:
true if tag has frame with this identifier

hasFrameAndBody

public boolean hasFrameAndBody(java.lang.String identifier)
Return whether tag has frame with this identifier and a related body. This is required to protect against circumstances whereby a tag contains a frame with an unsupported body but happens to have an identifier that is valid for another version of the tag which it has been converted to

e.g TDRC is an invalid frame in a v23 tag but if somehow a v23tag has been created by another application with a TDRC frame we construct an UnsupportedFrameBody to hold it, then this library constructs a v24 tag, it will contain a frame with id TDRC but it will not have the expected frame body it is not really a TDRC frame.

Parameters:
identifier - frameId to lookup
Returns:
true if tag has frame with this identifier

hasFrameOfType

public boolean hasFrameOfType(java.lang.String identifier)
Return whether tag has frame starting with this identifier

Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body but happens to have an identifier that is valid for another version of the tag it will return true

Parameters:
identifier - start of frameId to lookup
Returns:
tag has frame starting with this identifier

getFrame

public java.lang.Object getFrame(java.lang.String identifier)
For single frames return the frame in this tag with given identifier if it exists, if multiple frames exist with the same identifier it will return a list containing all the frames with this identifier

Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body but happens to have an identifier that is valid for another version of the tag it will be returned.

Parameters:
identifier - is an ID3Frame identifier
Returns:
matching frame, or list of matching frames

getFirst

public java.lang.String getFirst(java.lang.String identifier)
Retrieve the first value that exists for this identifier

If the value is a String it returns that, otherwise returns a summary of the fields information

Specified by:
getFirst in interface Tag
Parameters:
identifier -
Returns:

getFirstField

public TagField getFirstField(FieldKey genericKey)
                       throws KeyNotFoundException
Specified by:
getFirstField in interface Tag
Returns:
the first field that matches this generic key
Throws:
KeyNotFoundException

getFirstField

public AbstractID3v2Frame getFirstField(java.lang.String identifier)
Retrieve the first tagfield that exists for this identifier

Specified by:
getFirstField in interface Tag
Parameters:
identifier -
Returns:
tag field or null if doesnt exist

setFrame

public void setFrame(AbstractID3v2Frame frame)
Add a frame to this tag

Parameters:
frame - the frame to add

Warning if frame(s) already exists for this identifier thay are overwritten


getID3Frames

protected abstract ID3Frames getID3Frames()

setField

public void setField(FieldKey genericKey,
                     java.lang.String value)
              throws KeyNotFoundException,
                     FieldDataInvalidException
Description copied from interface: Tag
Create the field based on the generic key and set it in the tag

Specified by:
setField in interface Tag
Throws:
KeyNotFoundException
FieldDataInvalidException

addField

public void addField(FieldKey genericKey,
                     java.lang.String value)
              throws KeyNotFoundException,
                     FieldDataInvalidException
Description copied from interface: Tag
Create the field based on the generic key and add it to the tag

Specified by:
addField in interface Tag
Throws:
KeyNotFoundException
FieldDataInvalidException

mergeDuplicateFrames

public void mergeDuplicateFrames(AbstractID3v2Frame newFrame,
                                 java.util.List<AbstractID3v2Frame> frames)
Add frame taking into account existing frame sof the same type

Parameters:
newFrame -
frames -

setField

public void setField(TagField field)
              throws FieldDataInvalidException
Description copied from interface: Tag
Sets a field in the structure, used internally by the library

It is not recommended to use this method for normal use of the audiolibrary. The developer will circumvent the underlying implementation. For example, if one adds a field with the field id "TALB" for an mp3 file, and the given TagField implementation does not return a text field compliant data with TagField.getRawContent() other software and the audio library won't read the file correctly, if they do read it at all.
So for short:

  • The field is stored without validation
  • No conversion of data is perfomed
  • Specified by:
    setField in interface Tag
    Parameters:
    field -
    Throws:
    FieldDataInvalidException

    addField

    public void addField(TagField field)
                  throws FieldDataInvalidException
    Description copied from interface: Tag
    Adds a field to the structure, used internally by the library

    It is not recommended to use this method for normal use of the audiolibrary. The developer will circumvent the underlying implementation. For example, if one adds a field with the field id "TALB" for an mp3 file, and the given TagField implementation does not return a text field compliant data with TagField.getRawContent() other software and the audio library won't read the file correctly, if they do read it at all.
    So for short:

  • The field is stored without validation
  • No conversion of data is perfomed
  • Specified by:
    addField in interface Tag
    Parameters:
    field -
    Throws:
    FieldDataInvalidException

    setFrame

    public void setFrame(java.lang.String identifier,
                         java.util.List<AbstractID3v2Frame> multiFrame)
    Used for setting multiple frames for a single frame Identifier

    Warning if frame(s) already exists for this identifier thay are overwritten

    TODO needs to ensure do not add an invalid frame for this tag

    Parameters:
    identifier -
    multiFrame -

    getFrameCount

    public int getFrameCount()
    Return the number of frames in this tag of a particular type, multiple frames of the same time will only be counted once

    Returns:
    a count of different frames

    getFrameOfType

    public java.util.Iterator getFrameOfType(java.lang.String identifier)
    Return all frames which start with the identifier, this can be more than one which is useful if trying to retrieve similar frames e.g TIT1,TIT2,TIT3 ... and don't know exaclty which ones there are.

    Warning the match is only done against the identifier so if a tag contains a frame with an unsupported body but happens to have an identifier that is valid for another version of the tag it will be returned.

    Parameters:
    identifier -
    Returns:
    an iterator of all the frames starting with a particular identifier

    delete

    public void delete(java.io.RandomAccessFile file)
                throws java.io.IOException
    Delete Tag

    Specified by:
    delete in class AbstractTag
    Parameters:
    file - to delete the tag from
    Throws:
    java.io.IOException - if problem accessing the file


    equals

    public boolean equals(java.lang.Object obj)
    Is this tag equivalent to another

    Overrides:
    equals in class AbstractTag
    Parameters:
    obj - to test for equivalence
    Returns:
    true if they are equivalent

    iterator

    public java.util.Iterator iterator()
    Return the frames in the order they were added

    Specified by:
    iterator in class AbstractTag
    Returns:
    and iterator of the frmaes/list of multi value frames

    removeFrame

    public void removeFrame(java.lang.String identifier)
    Remove frame(s) with this identifier from tag

    Parameters:
    identifier - frameId to look for

    removeUnsupportedFrames

    public void removeUnsupportedFrames()
    Remove all frame(s) which have an unsupported body, in other words remove all frames that are not part of the standard frameset for this tag


    removeFrameOfType

    public void removeFrameOfType(java.lang.String identifier)
    Remove any frames starting with this identifier from tag

    Parameters:
    identifier - start of frameId to look for

    write

    public void write(java.io.File file,
                      long audioStartByte)
               throws java.io.IOException
    Write tag to file.

    Parameters:
    file -
    audioStartByte -
    Throws:
    java.io.IOException - TODO should be abstract

    getFileLockForWriting

    protected java.nio.channels.FileLock getFileLockForWriting(java.nio.channels.FileChannel fileChannel,
                                                               java.lang.String filePath)
                                                        throws java.io.IOException
    Get file lock for writing too file

    TODO:this appears to have little effect on Windows Vista

    Parameters:
    fileChannel -
    filePath -
    Returns:
    lock or null if locking is not supported
    Throws:
    java.io.IOException - if unable to get lock because already locked by another program
    java.nio.channels.OverlappingFileLockException - if already locked by another thread in the same VM, we dont catch this because indicates a programming error

    write

    public void write(java.io.RandomAccessFile file)
               throws java.io.IOException
    Write tag to file.

    Specified by:
    write in class AbstractTag
    Parameters:
    file -
    Throws:
    java.io.IOException - TODO should be abstract

    write

    public void write(java.nio.channels.WritableByteChannel channel)
               throws java.io.IOException
    Write tag to channel.

    Parameters:
    channel -
    Throws:
    java.io.IOException - TODO should be abstract

    getV2TagSizeIfExists

    public static long getV2TagSizeIfExists(java.io.File file)
                                     throws java.io.IOException
    Checks to see if the file contains an ID3tag and if so return its size as reported in the tag header and return the size of the tag (including header), if no such tag exists return zero.

    Parameters:
    file -
    Returns:
    the end of the tag in the file or zero if no tag exists.
    Throws:
    java.io.IOException

    seek

    public boolean seek(java.nio.ByteBuffer byteBuffer)
    Does a tag of the correct version exist in this file.

    Specified by:
    seek in class AbstractTag
    Parameters:
    byteBuffer - to search through
    Returns:
    true if tag exists.

    calculateTagSize

    protected int calculateTagSize(int tagSize,
                                   int audioStart)
    This method determines the total tag size taking into account where the audio file starts, the size of the tagging data and user options for defining how tags should shrink or grow.

    Parameters:
    tagSize -
    audioStart -
    Returns:

    adjustPadding

    public void adjustPadding(java.io.File file,
                              int paddingSize,
                              long audioStart)
                       throws java.io.FileNotFoundException,
                              java.io.IOException
    Adjust the length of the padding at the beginning of the MP3 file, this is only called when there is currently not enough space before the start of the audio to write the tag.

    A new file will be created with enough size to fit the ID3v2 tag. The old file will be deleted, and the new file renamed.

    Parameters:
    paddingSize - This is total size required to store tag before audio
    audioStart -
    file - The file to adjust the padding length of
    Throws:
    java.io.FileNotFoundException - if the file exists but is a directory rather than a regular file or cannot be opened for any other reason
    java.io.IOException - on any I/O error

    writeBufferToFile

    protected void writeBufferToFile(java.io.File file,
                                     java.nio.ByteBuffer headerBuffer,
                                     byte[] bodyByteBuffer,
                                     int padding,
                                     int sizeIncPadding,
                                     long audioStartLocation)
                              throws java.io.IOException
    Write the data from the buffer to the file

    Parameters:
    file -
    headerBuffer -
    bodyByteBuffer -
    padding -
    sizeIncPadding -
    audioStartLocation -
    Throws:
    java.io.IOException

    replaceFile

    private void replaceFile(java.io.File originalFile,
                             java.io.File newFile)
                      throws java.io.IOException
    Replace originalFile with the contents of newFile

    Both files must exist in the same folder so that there are no problems with fileystem mount points

    Parameters:
    newFile -
    originalFile -
    Throws:
    java.io.IOException

    copyFrameIntoMap

    protected void copyFrameIntoMap(java.lang.String id,
                                    AbstractID3v2Frame newFrame)

    loadFrameIntoMap

    protected void loadFrameIntoMap(java.lang.String frameId,
                                    AbstractID3v2Frame next)
    Decides what to with the frame that has just be read from file. If the frame is an allowable duplicate frame and is a duplicate we add all frames into an ArrayList and add the Arraylist to the hashMap. if not allowed to be duplicate we store bytes in the duplicateBytes variable.

    Parameters:
    frameId -
    next -

    getSize

    public int getSize()
    Return tag size based upon the sizes of the tags rather than the physical no of bytes between start of ID3Tag and start of Audio Data.Should be extended by subclasses to include header.

    Specified by:
    getSize in class AbstractTagItem
    Returns:
    size of the tag

    writeFramesToBuffer

    protected java.io.ByteArrayOutputStream writeFramesToBuffer()
                                                         throws java.io.IOException
    Write all the frames to the byteArrayOutputStream

    Currently Write all frames, defaults to the order in which they were loaded, newly created frames will be at end of tag.

    Returns:
    ByteBuffer Contains all the frames written within the tag ready for writing to file
    Throws:
    java.io.IOException

    getPreferredFrameOrderComparator

    public abstract java.util.Comparator getPreferredFrameOrderComparator()
    Returns:
    comparator used to order frames in preffrred order for writing to file so that most important frames are written first.

    createStructure

    public void createStructure()

    createStructureHeader

    public void createStructureHeader()

    createStructureBody

    public void createStructureBody()

    get

    public java.util.List<TagField> get(java.lang.String id)
                                 throws KeyNotFoundException
    Retrieve the values that exists for this id3 frame id

    Specified by:
    get in interface Tag
    Parameters:
    id - The field id.
    Returns:
    A list of TagField objects with the given "id".
    Throws:
    KeyNotFoundException

    getFirstGenre

    public java.lang.String getFirstGenre()
    Returns:

    getFirstTitle

    public java.lang.String getFirstTitle()
    Returns:

    getFirstTrack

    public java.lang.String getFirstTrack()
    Returns:

    getFirstYear

    public java.lang.String getFirstYear()
    Returns:

    getArtistId

    protected abstract java.lang.String getArtistId()
    Returns:

    getAlbumId

    protected abstract java.lang.String getAlbumId()
    Returns:

    getTitleId

    protected abstract java.lang.String getTitleId()
    Returns:

    getTrackId

    protected abstract java.lang.String getTrackId()
    Returns:

    getYearId

    protected abstract java.lang.String getYearId()
    Returns:

    getCommentId

    protected abstract java.lang.String getCommentId()
    Returns:

    getGenreId

    protected abstract java.lang.String getGenreId()
    Returns:

    createFrame

    public abstract AbstractID3v2Frame createFrame(java.lang.String id)
    Create Frame of correct ID3 version with the specified id

    Parameters:
    id -
    Returns:

    createArtistField

    public TagField createArtistField(java.lang.String content)
    Parameters:
    content -
    Returns:

    createAlbumField

    public TagField createAlbumField(java.lang.String content)
    Parameters:
    content -
    Returns:

    createTitleField

    public TagField createTitleField(java.lang.String content)
    Parameters:
    content -
    Returns:

    createTrackField

    public TagField createTrackField(java.lang.String content)
    Parameters:
    content -
    Returns:

    createYearField

    public TagField createYearField(java.lang.String content)
    Parameters:
    content -
    Returns:

    createCommentField

    public TagField createCommentField(java.lang.String content)
    Parameters:
    content -
    Returns:

    createGenreField

    public TagField createGenreField(java.lang.String content)
    Parameters:
    content -
    Returns:

    hasCommonFields

    public boolean hasCommonFields()
    Description copied from interface: Tag
    Returns true, if at least one of the contained fields is a common field (TagField.isCommon()).

    Specified by:
    hasCommonFields in interface Tag
    Returns:
    true if a common field is present.

    hasField

    public boolean hasField(java.lang.String id)
    Does this tag contain a field with the specified id

    Specified by:
    hasField in interface Tag
    Parameters:
    id - The field id to look for.
    Returns:
    true if tag contains a TagField with the given id.
    See Also:
    Tag.hasField(java.lang.String)

    isEmpty

    public boolean isEmpty()
    Is this tag empty

    Specified by:
    isEmpty in interface Tag
    Returns:
    true if tag contains no field.
    See Also:
    Tag.isEmpty()

    getFields

    public java.util.Iterator<TagField> getFields()
    Description copied from interface: Tag
    Iterator over all the fields within the tag, handle multiple fields with the same id

    Specified by:
    getFields in interface Tag
    Returns:
    iterator of all fields, multiple values for the same Id (e.g multiple TXXX frames) count as seperate fields

    getFieldCount

    public int getFieldCount()
    Description copied from interface: Tag
    Return the number of fields

    Fields with the same identifiers are counted seperately i.e two title fields would contribute two to the count

    Specified by:
    getFieldCount in interface Tag
    Returns:
    total number of fields

    setEncoding

    public boolean setEncoding(java.lang.String enc)
                        throws FieldDataInvalidException
    Specified by:
    setEncoding in interface Tag
    Throws:
    FieldDataInvalidException

    getFirst

    public java.lang.String getFirst(FieldKey genericKey)
                              throws KeyNotFoundException
    Retrieve the first value that exists for this generic key

    Specified by:
    getFirst in interface Tag
    Parameters:
    genericKey -
    Returns:
    Throws:
    KeyNotFoundException

    createField

    public TagField createField(FieldKey genericKey,
                                java.lang.String value)
                         throws KeyNotFoundException,
                                FieldDataInvalidException
    Create a new TagField

    Only textual data supported at the moment. The genericKey will be mapped to the correct implementation key and return a TagField.

    Specified by:
    createField in interface Tag
    Parameters:
    genericKey - is the generic key
    value - to store
    Returns:
    Throws:
    KeyNotFoundException
    FieldDataInvalidException

    doCreateTagField

    protected TagField doCreateTagField(AbstractID3v2Tag.FrameAndSubId formatKey,
                                        java.lang.String value)
                                 throws KeyNotFoundException,
                                        FieldDataInvalidException
    Create Frame for Id3 Key

    Only textual data supported at the moment, should only be used with frames that support a simple string argument.

    Parameters:
    formatKey -
    value -
    Returns:
    Throws:
    KeyNotFoundException
    FieldDataInvalidException

    doGetFirst

    protected java.lang.String doGetFirst(AbstractID3v2Tag.FrameAndSubId formatKey)
                                   throws KeyNotFoundException
    Parameters:
    formatKey -
    Returns:
    Throws:
    KeyNotFoundException

    createLinkedArtworkField

    public TagField createLinkedArtworkField(java.lang.String url)
    Create a link to artwork, this is not recommended because the link may be broken if the mp3 or image file is moved

    Parameters:
    url - specifies the link, it could be a local file or could be a full url
    Returns:

    deleteField

    public void deleteField(FieldKey genericKey)
                     throws KeyNotFoundException
    Delete fields with this generic key

    Specified by:
    deleteField in interface Tag
    Parameters:
    genericKey -
    Throws:
    KeyNotFoundException

    doDeleteTagField

    protected void doDeleteTagField(AbstractID3v2Tag.FrameAndSubId formatKey)
                             throws KeyNotFoundException
    Internal delete method

    Parameters:
    formatKey -
    Throws:
    KeyNotFoundException

    getFrameAndSubIdFromGenericKey

    protected abstract AbstractID3v2Tag.FrameAndSubId getFrameAndSubIdFromGenericKey(FieldKey genericKey)

    getFields

    public java.util.List<TagField> getFields(FieldKey genericKey)
                                       throws KeyNotFoundException
    Get field(s) for this key

    Specified by:
    getFields in interface Tag
    Parameters:
    genericKey -
    Returns:
    Throws:
    KeyNotFoundException

    getFirstArtwork

    public Artwork getFirstArtwork()
    Specified by:
    getFirstArtwork in interface Tag
    Returns:
    first artwork or null if none exist

    setField

    public void setField(Artwork artwork)
                  throws FieldDataInvalidException
    Create field and then set within tag itself

    Specified by:
    setField in interface Tag
    Parameters:
    artwork -
    Throws:
    FieldDataInvalidException

    addField

    public void addField(Artwork artwork)
                  throws FieldDataInvalidException
    Create field and then set within tag itself

    Specified by:
    addField in interface Tag
    Parameters:
    artwork -
    Throws:
    FieldDataInvalidException

    deleteArtworkField

    public void deleteArtworkField()
                            throws KeyNotFoundException
    Delete all instance of artwork Field

    Specified by:
    deleteArtworkField in interface Tag
    Throws:
    KeyNotFoundException