FileDocCategorySizeDatePackage
AbstractID3v2Frame.javaAPI DocJaudiotagger 2.0.421762Wed Jun 08 12:05:40 BST 2011org.jaudiotagger.tag.id3

AbstractID3v2Frame

public abstract class AbstractID3v2Frame extends AbstractTagFrame implements TagTextField
This abstract class is each frame header inside a ID3v2 tag.
author
: Paul Taylor
author
: Eric Farng
version
$Id: AbstractID3v2Frame.java 976 2011-06-08 10:05:34Z paultaylor $

Fields Summary
protected static final String
TYPE_FRAME
protected static final String
TYPE_FRAME_SIZE
protected static final String
UNSUPPORTED_ID
protected String
identifier
protected int
frameSize
private String
loggingFilename
StatusFlags
statusFlags
This holds the Status flags (not supported in v2.20
EncodingFlags
encodingFlags
This holds the Encoding flags (not supported in v2.20)
Constructors Summary
protected AbstractID3v2Frame()
Create an empty frame


                 
       

                   
       

                  
       

             
     
    
        
public AbstractID3v2Frame(AbstractID3v2Frame frame)
Create a frame based on another frame

param
frame


                  
      
    
        super(frame);
    
public AbstractID3v2Frame(org.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBody body)
Create a frame based on a body

param
body

        this.frameBody = body;
        this.frameBody.setHeader(this);
    
public AbstractID3v2Frame(String identifier)
Create a new frame with empty body based on identifier

param
identifier

        logger.config("Creating empty frame of type" + identifier);
        this.identifier = identifier;

        // Use reflection to map id to frame body, which makes things much easier
        // to keep things up to date.
        try
        {
            Class<AbstractID3v2FrameBody> c = (Class<AbstractID3v2FrameBody>) Class.forName("org.jaudiotagger.tag.id3.framebody.FrameBody" + identifier);
            frameBody = c.newInstance();
        }
        catch (ClassNotFoundException cnfe)
        {
            logger.severe(cnfe.getMessage());
            frameBody = new FrameBodyUnsupported(identifier);
        }
        //Instantiate Interface/Abstract should not happen
        catch (InstantiationException ie)
        {
            logger.log(Level.SEVERE, "InstantiationException:" + identifier, ie);
            throw new RuntimeException(ie);
        }
        //Private Constructor shouild not happen
        catch (IllegalAccessException iae)
        {
            logger.log(Level.SEVERE, "IllegalAccessException:" + identifier, iae);
            throw new RuntimeException(iae);
        }
        frameBody.setHeader(this);
        if (this instanceof ID3v24Frame)
        {
            frameBody.setTextEncoding(TagOptionSingleton.getInstance().getId3v24DefaultTextEncoding());
        }
        else if (this instanceof ID3v23Frame)
        {
            frameBody.setTextEncoding(TagOptionSingleton.getInstance().getId3v23DefaultTextEncoding());
        }

        logger.config("Created empty frame of type" + identifier);
    
Methods Summary
public voidcopyContent(TagField field)


    
public voidcreateStructure()
Return String Representation of frame

        MP3File.getStructureFormatter().openHeadingElement(TYPE_FRAME, getIdentifier());
        MP3File.getStructureFormatter().closeHeadingElement(TYPE_FRAME);
    
public booleanequals(java.lang.Object obj)

        if ( this == obj ) return true;
        if (!(obj instanceof AbstractID3v2Frame))
        {
            return false;
        }

        AbstractID3v2Frame that = (AbstractID3v2Frame) obj;
        return super.equals(that);
    
public java.lang.StringgetContent()
Returns the content of the field. For frames consisting of different fields, this will return the value deemed to be most likely to be required

return
Content

        return getBody().getUserFriendlyValue();
    
public java.lang.StringgetEncoding()
Returns the current used charset encoding.

return
Charset encoding.

        return TextEncoding.getInstanceOf().getValueForId(this.getBody().getTextEncoding());
    
public org.jaudiotagger.tag.id3.AbstractID3v2Frame$EncodingFlagsgetEncodingFlags()

        return encodingFlags;
    
protected abstract intgetFrameHeaderSize()

return
the size in bytes of the frame header

protected abstract intgetFrameIdSize()

return
size in bytes of the frameid field

protected abstract intgetFrameSizeSize()

return
the size in bytes of the frame size field

public java.lang.StringgetId()
Return the frame identifier, this only identifies the frame it does not provide a unique key, when using frames such as TXXX which are used by many fields *

return
the frame identifier (Tag Field Interface)

        return getIdentifier();
    
public java.lang.StringgetIdentifier()
Return the frame identifier

return
the frame identifier

        return identifier;
    
protected java.lang.StringgetLoggingFilename()
Retrieve the logging filename to be used in debugging

return
logging filename to be used in debugging

        return loggingFilename;
    
public byte[]getRawContent()

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        write(baos);
        return baos.toByteArray();
    
public org.jaudiotagger.tag.id3.AbstractID3v2Frame$StatusFlagsgetStatusFlags()

        return statusFlags;
    
public voidisBinary(boolean b)

param
b

        //do nothing because whether or not a field is binary is defined by its id and is immutable
    
public booleanisEmpty()

        AbstractTagFrameBody body = this.getBody();
        if (body == null)
        {
            return true;
        }
        //TODO depends on the body
        return false;
    
protected booleanisPadding(byte[] buffer)

        if(
                (buffer[0]=='\0")&&
                (buffer[1]=='\0")&&
                (buffer[2]=='\0")&&
                (buffer[3]=='\0")
           )
        {
            return true;
        }
        return false;
    
protected org.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBodyreadBody(java.lang.String identifier, java.nio.ByteBuffer byteBuffer, int frameSize)
Read the frame body from the specified file via the buffer

param
identifier the frame identifier
param
byteBuffer to read the frame body from
param
frameSize
return
a newly created FrameBody
throws
InvalidFrameException unable to construct a framebody from the data

        //Use reflection to map id to frame body, which makes things much easier
        //to keep things up to date,although slight performance hit.
        logger.finest("Creating framebody:start");

        AbstractID3v2FrameBody frameBody;
        try
        {
            Class<AbstractID3v2FrameBody> c = (Class<AbstractID3v2FrameBody>) Class.forName("org.jaudiotagger.tag.id3.framebody.FrameBody" + identifier);
            Class<?>[] constructorParameterTypes = {Class.forName("java.nio.ByteBuffer"), Integer.TYPE};
            Object[] constructorParameterValues = {byteBuffer, frameSize};
            Constructor<AbstractID3v2FrameBody> construct = c.getConstructor(constructorParameterTypes);
            frameBody = (construct.newInstance(constructorParameterValues));
        }
        //No class defined for this frame type,use FrameUnsupported
        catch (ClassNotFoundException cex)
        {
            logger.config(getLoggingFilename() + ":" + "Identifier not recognised:" + identifier + " using FrameBodyUnsupported");
            try
            {
                frameBody = new FrameBodyUnsupported(byteBuffer, frameSize);
            }
            //Should only throw InvalidFrameException but unfortunately legacy hierachy forces
            //read method to declare it can throw InvalidtagException
            catch (InvalidFrameException ife)
            {
                throw ife;
            }
            catch (InvalidTagException te)
            {
                throw new InvalidFrameException(te.getMessage());
            }
        }
        //An error has occurred during frame instantiation, if underlying cause is an unchecked exception or error
        //propagate it up otherwise mark this frame as invalid
        catch (InvocationTargetException ite)
        {
            logger.severe(getLoggingFilename() + ":" + "An error occurred within abstractID3v2FrameBody for identifier:" + identifier + ":" + ite.getCause().getMessage());
            if (ite.getCause() instanceof Error)
            {
                throw (Error) ite.getCause();
            }
            else if (ite.getCause() instanceof RuntimeException)
            {
                throw (RuntimeException) ite.getCause();
            }
            else if(ite.getCause() instanceof  InvalidFrameException )
            {
                throw (InvalidFrameException)ite.getCause();
            }
            else if(ite.getCause() instanceof  InvalidDataTypeException )
            {
                throw (InvalidDataTypeException)ite.getCause();
            }
            else
            {
                throw new InvalidFrameException(ite.getCause().getMessage());
            }
        }
        //No Such Method should not happen
        catch (NoSuchMethodException sme)
        {
            logger.log(Level.SEVERE, getLoggingFilename() + ":" + "No such method:" + sme.getMessage(), sme);
            throw new RuntimeException(sme.getMessage());
        }
        //Instantiate Interface/Abstract should not happen
        catch (InstantiationException ie)
        {
            logger.log(Level.SEVERE, getLoggingFilename() + ":" + "Instantiation exception:" + ie.getMessage(), ie);
            throw new RuntimeException(ie.getMessage());
        }
        //Private Constructor shouild not happen
        catch (IllegalAccessException iae)
        {
            logger.log(Level.SEVERE, getLoggingFilename() + ":" + "Illegal access exception :" + iae.getMessage(), iae);
            throw new RuntimeException(iae.getMessage());
        }
        logger.finest(getLoggingFilename() + ":" + "Created framebody:end" + frameBody.getIdentifier());
        frameBody.setHeader(this);
        return frameBody;
    
protected org.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBodyreadBody(java.lang.String identifier, org.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBody body)
This creates a new body based of type identifier but populated by the data in the body. This is a different type to the body being created which is why TagUtility.copyObject() can't be used. This is used when converting between different versions of a tag for frames that have a non-trivial mapping such as TYER in v3 to TDRC in v4. This will only work where appropriate constructors exist in the frame body to be created, for example a FrameBodyTYER requires a constructor consisting of a FrameBodyTDRC.

If this method is called and a suitable constructor does not exist then an InvalidFrameException will be thrown

param
identifier to determine type of the frame
param
body
return
newly created framebody for this type
throws
InvalidFrameException if unable to construct a framebody for the identifier and body provided.

        /* Use reflection to map id to frame body, which makes things much easier
         * to keep things up to date, although slight performance hit.
         */
        AbstractID3v2FrameBody frameBody;
        try
        {
            Class<AbstractID3v2FrameBody> c = (Class<AbstractID3v2FrameBody>) Class.forName("org.jaudiotagger.tag.id3.framebody.FrameBody" + identifier);
            Class<?>[] constructorParameterTypes = {body.getClass()};
            Object[] constructorParameterValues = {body};
            Constructor<AbstractID3v2FrameBody> construct = c.getConstructor(constructorParameterTypes);
            frameBody = (construct.newInstance(constructorParameterValues));
        }
        catch (ClassNotFoundException cex)
        {
            logger.config("Identifier not recognised:" + identifier + " unable to create framebody");
            throw new InvalidFrameException("FrameBody" + identifier + " does not exist");
        }
        //If suitable constructor does not exist
        catch (NoSuchMethodException sme)
        {
            logger.log(Level.SEVERE, "No such method:" + sme.getMessage(), sme);
            throw new InvalidFrameException("FrameBody" + identifier + " does not have a constructor that takes:" + body.getClass().getName());
        }
        catch (InvocationTargetException ite)
        {
            logger.severe("An error occurred within abstractID3v2FrameBody");
            logger.log(Level.SEVERE, "Invocation target exception:" + ite.getCause().getMessage(), ite.getCause());
            if (ite.getCause() instanceof Error)
            {
                throw (Error) ite.getCause();
            }
            else if (ite.getCause() instanceof RuntimeException)
            {
                throw (RuntimeException) ite.getCause();
            }
            else
            {
                throw new InvalidFrameException(ite.getCause().getMessage());
            }
        }

        //Instantiate Interface/Abstract should not happen
        catch (InstantiationException ie)
        {
            logger.log(Level.SEVERE, "Instantiation exception:" + ie.getMessage(), ie);
            throw new RuntimeException(ie.getMessage());
        }
        //Private Constructor shouild not happen
        catch (IllegalAccessException iae)
        {
            logger.log(Level.SEVERE, "Illegal access exception :" + iae.getMessage(), iae);
            throw new RuntimeException(iae.getMessage());
        }

        logger.finer("frame Body created" + frameBody.getIdentifier());
        frameBody.setHeader(this);
        return frameBody;
    
protected org.jaudiotagger.tag.id3.framebody.AbstractID3v2FrameBodyreadEncryptedBody(java.lang.String identifier, java.nio.ByteBuffer byteBuffer, int frameSize)
Read the frameBody when frame marked as encrypted

param
identifier
param
byteBuffer
param
frameSize
return
throws
InvalidFrameException
throws
InvalidDataTypeException
throws
InvalidTagException

        try
        {
            AbstractID3v2FrameBody frameBody = new  FrameBodyEncrypted(identifier,byteBuffer, frameSize);
            frameBody.setHeader(this);
            return frameBody;
        }
        catch(InvalidTagException ite)
        {
            throw new InvalidDataTypeException(ite);
        }
    
protected java.lang.StringreadIdentifier(java.nio.ByteBuffer byteBuffer)
Get the next frame id, throwing an exception if unable to do this and check against just having padded data

param
byteBuffer
return
throws
PaddingException
throws
InvalidFrameException

        byte[] buffer = new byte[getFrameIdSize()];

        if (byteBuffer.position() + getFrameHeaderSize() >= byteBuffer.limit())
        {
            logger.warning(getLoggingFilename() + ":" + "No space to find another frame:");
            throw new InvalidFrameException(getLoggingFilename() + ":" + "No space to find another frame");
        }

        //Read the Frame Identifier
        byteBuffer.get(buffer, 0, getFrameIdSize());

        if(isPadding(buffer))
        {
            throw new PaddingException(getLoggingFilename() + ":only padding found");
        }

        identifier = new String(buffer);
        logger.fine(getLoggingFilename() + ":" + "Identifier is" + identifier);
        return identifier;
    
public voidsetContent(java.lang.String content)
Sets the content of the field.

param
content fields content.

        throw new UnsupportedOperationException("Not implemeneted please use the generic tag methods for setting content");
    
protected voidsetLoggingFilename(java.lang.String loggingFilename)
Set logging filename when construct tag for read from file

param
loggingFilename

        this.loggingFilename = loggingFilename;
    
public abstract voidwrite(java.io.ByteArrayOutputStream tagBuffer)