Coverage Report - org.jaudiotagger.tag.datatype.MultipleTextEncodedStringNullTerminated
 
Classes in this File Line Coverage Branch Coverage Complexity
MultipleTextEncodedStringNullTerminated
76%
36/47
50%
7/14
2.077
MultipleTextEncodedStringNullTerminated$Values
100%
15/15
100%
4/4
2.077
 
 1  
 package org.jaudiotagger.tag.datatype;
 2  
 
 3  
 import org.jaudiotagger.tag.InvalidDataTypeException;
 4  
 import org.jaudiotagger.tag.id3.AbstractTagFrameBody;
 5  
 
 6  
 import java.io.ByteArrayOutputStream;
 7  
 import java.io.IOException;
 8  
 import java.util.ArrayList;
 9  
 import java.util.List;
 10  
 import java.util.ListIterator;
 11  
 import java.util.logging.Level;
 12  
 
 13  
 /**
 14  
  * Represents a datatype that supports multiple terminated Strings (there may only be one)
 15  
  */
 16  
 public class MultipleTextEncodedStringNullTerminated extends AbstractDataType
 17  
 {
 18  
 
 19  
     /**
 20  
      * Creates a new ObjectStringSizeTerminated datatype.
 21  
      *
 22  
      * @param identifier identifies the frame type
 23  
      * @param frameBody
 24  
      */
 25  
     public MultipleTextEncodedStringNullTerminated(String identifier, AbstractTagFrameBody frameBody)
 26  
     {
 27  18
         super(identifier, frameBody);
 28  18
         value = new MultipleTextEncodedStringNullTerminated.Values();
 29  18
     }
 30  
 
 31  
     public MultipleTextEncodedStringNullTerminated(TextEncodedStringSizeTerminated object)
 32  
     {
 33  0
         super(object);
 34  0
         value = new MultipleTextEncodedStringNullTerminated.Values();
 35  0
     }
 36  
 
 37  
     public MultipleTextEncodedStringNullTerminated(MultipleTextEncodedStringNullTerminated object)
 38  
     {
 39  1
         super(object);        
 40  1
     }
 41  
 
 42  
     public boolean equals(Object obj)
 43  
     {
 44  0
         return obj instanceof MultipleTextEncodedStringNullTerminated && super.equals(obj);
 45  
     }
 46  
 
 47  
     /**
 48  
      * Returns the size in bytes of this datatype when written to file
 49  
      *
 50  
      * @return size of this datatype
 51  
      */
 52  
     public int getSize()
 53  
     {
 54  10
         return size;
 55  
     }
 56  
 
 57  
     /**
 58  
      * Check the value can be encoded with the specified encoding
 59  
      * @return
 60  
      */
 61  
     public boolean canBeEncoded()
 62  
     {
 63  4
         for (ListIterator<String> li = ((Values) value).getList().listIterator(); li.hasNext();)
 64  
         {
 65  4
             TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody, li.next());
 66  4
             if (!next.canBeEncoded())
 67  
             {
 68  0
                 return false;
 69  
             }
 70  4
         }
 71  4
         return true;
 72  
     }
 73  
 
 74  
     /**
 75  
      * Read Null Terminated Strings from the array starting at offset, continue until unable to find any null terminated
 76  
      * Strings or until reached the end of the array. The offset should be set to byte after the last null terminated
 77  
      * String found.
 78  
      *
 79  
      * @param arr    to read the Strings from
 80  
      * @param offset in the array to start reading from
 81  
      * @throws InvalidDataTypeException if unable to find any null terminated Strings
 82  
      */
 83  
     public void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException
 84  
     {
 85  6
         logger.finer("Reading MultipleTextEncodedStringNullTerminated from array from offset:" + offset);
 86  
         //Continue until unable to read a null terminated String
 87  
         while (true)
 88  
         {
 89  
             try
 90  
             {
 91  
                 //Read String
 92  19
                 TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody);
 93  19
                 next.readByteArray(arr, offset);
 94  
 
 95  13
                 if (next.getSize() == 0)
 96  
                 {
 97  0
                     break;
 98  
                 }
 99  
                 else
 100  
                 {
 101  
                     //Add to value
 102  13
                     ((Values) value).add((String) next.getValue());
 103  
 
 104  
                     //Add to size calculation
 105  13
                     size += next.getSize();
 106  
 
 107  
                     //Increment Offset to start of next datatype.
 108  13
                     offset += next.getSize();
 109  
                 }
 110  
             }
 111  6
             catch (InvalidDataTypeException idte)
 112  
             {
 113  6
                 break;
 114  13
             }
 115  
 
 116  13
             if (size == 0)
 117  
             {
 118  0
                 logger.warning("No null terminated Strings found");
 119  0
                 throw new InvalidDataTypeException("No null terminated Strings found");
 120  
             }
 121  
         }
 122  6
         logger.finer("Read  MultipleTextEncodedStringNullTerminated:" + value + " size:" + size);
 123  6
     }
 124  
 
 125  
     /**
 126  
      * For every String write to bytebuffer
 127  
      *
 128  
      * @return bytebuffer that should be written to file to persist this datatype.
 129  
      */
 130  
     public byte[] writeByteArray()
 131  
     {
 132  4
         logger.finer("Writing MultipleTextEncodedStringNullTerminated");
 133  
 
 134  4
         int localSize = 0;
 135  4
         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
 136  
         try
 137  
         {
 138  4
             for (ListIterator<String> li = ((Values) value).getList().listIterator(); li.hasNext();)
 139  
             {
 140  4
                 TextEncodedStringNullTerminated next = new TextEncodedStringNullTerminated(identifier, frameBody, li.next());
 141  4
                 buffer.write(next.writeByteArray());
 142  4
                 localSize += next.getSize();
 143  4
             }
 144  
         }
 145  0
         catch (IOException ioe)
 146  
         {
 147  
             //This should never happen because the write is internal with the JVM it is not to a file
 148  0
             logger.log(Level.SEVERE, "IOException in MultipleTextEncodedStringNullTerminated when writing byte array", ioe);
 149  0
             throw new RuntimeException(ioe);
 150  4
         }
 151  
 
 152  
         //Update size member variable
 153  4
         size = localSize;
 154  
 
 155  4
         logger.finer("Written MultipleTextEncodedStringNullTerminated");
 156  4
         return buffer.toByteArray();
 157  
     }
 158  
 
 159  
     /**
 160  
      * This holds the values held by a MultipleTextEncodedDatatype
 161  
      */
 162  
     public static class Values
 163  
     {
 164  40
         private List<String> valueList = new ArrayList<String>();
 165  
 
 166  
         public Values()
 167  40
         {
 168  
 
 169  40
         }
 170  
 
 171  
         /**
 172  
          * Add String Datatype to the value list
 173  
          *
 174  
          * @param value to add to the list
 175  
          */
 176  
         public void add(String value)
 177  
         {
 178  17
             valueList.add(value);
 179  17
         }
 180  
 
 181  
 
 182  
         /**
 183  
          * Return the list of values
 184  
          *
 185  
          * @return the list of values
 186  
          */
 187  
         public List<String> getList()
 188  
         {
 189  19
             return valueList;
 190  
         }
 191  
 
 192  
         /**
 193  
          *
 194  
          * @return no of values
 195  
          */
 196  
         public int getNumberOfValues()
 197  
         {
 198  6
             return valueList.size();
 199  
         }
 200  
 
 201  
         /**
 202  
          * Return the list of values as a single string seperated by a comma
 203  
          *
 204  
          * @return a string representation of the value
 205  
          */
 206  
         public String toString()
 207  
         {
 208  12
             StringBuffer sb = new StringBuffer();
 209  12
             for (ListIterator<String> li = valueList.listIterator(); li.hasNext();)
 210  
             {
 211  26
                 String next = li.next();
 212  26
                 sb.append(next);
 213  26
                 if (li.hasNext())
 214  
                 {
 215  14
                     sb.append(",");
 216  
                 }
 217  26
             }
 218  12
             return sb.toString();
 219  
         }
 220  
     }
 221  
 }