FileDocCategorySizeDatePackage
MultipleTextEncodedStringNullTerminated.javaAPI DocJaudiotagger 2.0.46860Wed Mar 30 16:12:12 BST 2011org.jaudiotagger.tag.datatype

MultipleTextEncodedStringNullTerminated.java

package org.jaudiotagger.tag.datatype;

import org.jaudiotagger.tag.InvalidDataTypeException;
import org.jaudiotagger.tag.id3.AbstractTagFrameBody;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.logging.Level;

/**
 * Represents a data type that supports multiple terminated Strings (there may only be one)
 */
public class MultipleTextEncodedStringNullTerminated extends AbstractDataType
{

    /**
     * Creates a new ObjectStringSizeTerminated datatype.
     *
     * @param identifier identifies the frame type
     * @param frameBody
     */
    public MultipleTextEncodedStringNullTerminated(String identifier, AbstractTagFrameBody frameBody)
    {
        super(identifier, frameBody);
        value = new MultipleTextEncodedStringNullTerminated.Values();
    }

    public MultipleTextEncodedStringNullTerminated(TextEncodedStringSizeTerminated object)
    {
        super(object);
        value = new MultipleTextEncodedStringNullTerminated.Values();
    }

    public MultipleTextEncodedStringNullTerminated(MultipleTextEncodedStringNullTerminated object)
    {
        super(object);        
    }

    public boolean equals(Object obj)
    {
        return obj instanceof MultipleTextEncodedStringNullTerminated && super.equals(obj);
    }

    /**
     * Returns the size in bytes of this datatype when written to file
     *
     * @return size of this datatype
     */
    public int getSize()
    {
        return size;
    }

    /**
     * Check the value can be encoded with the specified encoding
     * @return
     */
    public boolean canBeEncoded()
    {
        for (ListIterator<String> li = ((Values) value).getList().listIterator(); li.hasNext();)
        {
            TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody, li.next());
            if (!next.canBeEncoded())
            {
                return false;
            }
        }
        return true;
    }

    /**
     * Read Null Terminated Strings from the array starting at offset, continue until unable to find any null terminated
     * Strings or until reached the end of the array. The offset should be set to byte after the last null terminated
     * String found.
     *
     * @param arr    to read the Strings from
     * @param offset in the array to start reading from
     * @throws InvalidDataTypeException if unable to find any null terminated Strings
     */
    public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException
    {
        logger.finer("Reading MultipleTextEncodedStringNullTerminated from array from offset:" + offset);
        //Continue until unable to read a null terminated String
        while (true)
        {
            try
            {
                //Read String
                TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody);
                next.readByteArray(arr, offset);

                if (next.getSize() == 0)
                {
                    break;
                }
                else
                {
                    //Add to value
                    ((Values) value).add((String) next.getValue());

                    //Add to size calculation
                    size += next.getSize();

                    //Increment Offset to start of next datatype.
                    offset += next.getSize();
                }
            }
            catch (InvalidDataTypeException idte)
            {
                break;
            }

            if (size == 0)
            {
                logger.warning("No null terminated Strings found");
                throw new InvalidDataTypeException("No null terminated Strings found");
            }
        }
        logger.finer("Read  MultipleTextEncodedStringNullTerminated:" + value + " size:" + size);
    }

    /**
     * For every String write to bytebuffer
     *
     * @return bytebuffer that should be written to file to persist this datatype.
     */
    public byte[] writeByteArray()
    {
        logger.finer("Writing MultipleTextEncodedStringNullTerminated");

        int localSize = 0;
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        try
        {
            for (ListIterator<String> li = ((Values) value).getList().listIterator(); li.hasNext();)
            {
                TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody, li.next());
                buffer.write(next.writeByteArray());
                localSize += next.getSize();
            }
        }
        catch (IOException ioe)
        {
            //This should never happen because the write is internal with the JVM it is not to a file
            logger.log(Level.SEVERE, "IOException in MultipleTextEncodedStringNullTerminated when writing byte array", ioe);
            throw new RuntimeException(ioe);
        }

        //Update size member variable
        size = localSize;

        logger.finer("Written MultipleTextEncodedStringNullTerminated");
        return buffer.toByteArray();
    }

    /**
     * This holds the values held by a MultipleTextEncodedData type
     */
    public static class Values
    {
        private List<String> valueList = new ArrayList<String>();

        public Values()
        {

        }

        /**
         * Add String Data type to the value list
         *
         * @param value to add to the list
         */
        public void add(String value)
        {
            valueList.add(value);
        }


        /**
         * Return the list of values
         *
         * @return the list of values
         */
        public List<String> getList()
        {
            return valueList;
        }

        /**
         *
         * @return no of values
         */
        public int getNumberOfValues()
        {
            return valueList.size();
        }

        /**
         * Return the list of values as a single string separated by a comma
         *
         * @return a string representation of the value
         */
        public String toString()
        {
            StringBuffer sb = new StringBuffer();
            for (ListIterator<String> li = valueList.listIterator(); li.hasNext();)
            {
                String next = li.next();
                sb.append(next);
                if (li.hasNext())
                {
                    sb.append(",");
                }
            }
            return sb.toString();
        }
    }
}