Coverage Report - org.jaudiotagger.tag.id3.AbstractTagFrameBody
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractTagFrameBody
64%
43/67
50%
19/38
0
 
 1  
 /**
 2  
  *  @author : Paul Taylor
 3  
  *  @author : Eric Farng
 4  
  *
 5  
  *  Version @version:$Id: AbstractTagFrameBody.java,v 1.4 2008/07/21 10:45:47 paultaylor Exp $
 6  
  *
 7  
  *  MusicTag Copyright (C)2003,2004
 8  
  *
 9  
  *  This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
 10  
  *  General Public  License as published by the Free Software Foundation; either version 2.1 of the License,
 11  
  *  or (at your option) any later version.
 12  
  *
 13  
  *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 14  
  *  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 15  
  *  See the GNU Lesser General Public License for more details.
 16  
  *
 17  
  *  You should have received a copy of the GNU Lesser General Public License along with this library; if not,
 18  
  *  you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software
 19  
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 20  
  *
 21  
  *  FragmentBody contains the data for a fragment.
 22  
  * ID3v2 tags have frames bodys. Lyrics3 tags have fields bodys
 23  
  * ID3v1 tags do not have fragments bodys.
 24  
  * Fragment Bodies consist of a number of MP3Objects held in an objectList
 25  
  * Methods are additionally defined here to restrieve and set these objects.
 26  
  * We also specify methods for getting/setting the text encoding of textual
 27  
  * data.
 28  
  * Fragment bodies should not be concerned about their parent fragment. For
 29  
  * example most ID3v2 frames can be applied to ID3v2tags of different versions.
 30  
  * The frame header will need modification based on the frame version but this
 31  
  * should have no effect on the frame body.
 32  
  */
 33  
 package org.jaudiotagger.tag.id3;
 34  
 
 35  
 import org.jaudiotagger.tag.datatype.AbstractDataType;
 36  
 import org.jaudiotagger.tag.datatype.DataTypes;
 37  
 import org.jaudiotagger.tag.id3.valuepair.TextEncoding;
 38  
 
 39  
 import java.util.ArrayList;
 40  
 import java.util.Iterator;
 41  
 
 42  
 /**
 43  
  * A frame body contains the data content for a frame
 44  
  */
 45  
 public abstract class AbstractTagFrameBody extends AbstractTagItem
 46  
 {
 47  
     public void createStructure()
 48  
     {
 49  0
     }
 50  
 
 51  
     /**
 52  
      * Reference to the header associated with this frame body, a framebody can be created without a header
 53  
      * but one it is associated with a header this should be set. It is principally useful for the framebody to know
 54  
      * its header, because this will specify its tag version and some framebodies behave slighly different
 55  
      * between tag versions.
 56  
      */
 57  
     private AbstractTagFrame header;
 58  
 
 59  
     /**
 60  
      * List of data types that make up this particular frame body.
 61  
      */
 62  3317
     protected ArrayList<AbstractDataType> objectList = new ArrayList<AbstractDataType>();
 63  
 
 64  
     /**
 65  
      * Return the Text Encoding
 66  
      *
 67  
      * @return the text encoding used by this framebody
 68  
      */
 69  
     public final byte getTextEncoding()
 70  
     {
 71  5374
         AbstractDataType o = getObject(DataTypes.OBJ_TEXT_ENCODING);
 72  
 
 73  5374
         if (o != null)
 74  
         {
 75  5354
             Long encoding = (Long) (o.getValue());
 76  5354
             return encoding.byteValue();
 77  
         }
 78  
         else
 79  
         {
 80  20
             return TextEncoding.ISO_8859_1;
 81  
         }
 82  
     }
 83  
 
 84  
     /**
 85  
      * Set the Text Encoding to use for this frame body
 86  
      *
 87  
      * @param textEncoding to use for this frame body
 88  
      */
 89  
     public final void setTextEncoding(byte textEncoding)
 90  
     {
 91  
         //Number HashMap actually converts this byte to a long
 92  1270
         setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding);
 93  1270
     }
 94  
 
 95  
 
 96  
     /**
 97  
      * Creates a new framebody, at this point the bodys
 98  
      * ObjectList is setup which defines what datatypes are expected in body
 99  
      */
 100  
     protected AbstractTagFrameBody()
 101  2135
     {
 102  2135
         setupObjectList();
 103  2135
     }
 104  
 
 105  
     /**
 106  
      * Copy Constructor for fragment body. Copies all objects in the
 107  
      * Object Iterator with data.
 108  
      */
 109  
     protected AbstractTagFrameBody(AbstractTagFrameBody copyObject)
 110  1182
     {
 111  
         AbstractDataType newObject;
 112  4075
         for (int i = 0; i < copyObject.objectList.size(); i++)
 113  
         {
 114  2893
             newObject = (AbstractDataType) ID3Tags.copyObject(copyObject.objectList.get(i));
 115  2893
             newObject.setBody(this);
 116  2893
             this.objectList.add(newObject);
 117  
         }
 118  1182
     }
 119  
 
 120  
 
 121  
     /**
 122  
      * This method calls <code>toString</code> for all it's objects and appends
 123  
      * them without any newline characters.
 124  
      *
 125  
      * @return brief description string
 126  
      */
 127  
     public String getBriefDescription()
 128  
     {
 129  2
         String str = "";
 130  2
         for (AbstractDataType object : objectList)
 131  
         {
 132  4
             if ((object.toString() != null) && (object.toString().length() > 0))
 133  
             {
 134  2
                 str += (object.getIdentifier() + "=\"" + object.toString() + "\"; ");
 135  
             }
 136  
         }
 137  2
         return str;
 138  
     }
 139  
 
 140  
 
 141  
     /**
 142  
      * This method calls <code>toString</code> for all it's objects and appends
 143  
      * them. It contains new line characters and is more suited for display
 144  
      * purposes
 145  
      *
 146  
      * @return formatted description string
 147  
      */
 148  
     public final String getLongDescription()
 149  
     {
 150  0
         String str = "";
 151  0
         for (AbstractDataType object : objectList)
 152  
         {
 153  0
             if ((object.toString() != null) && (object.toString().length() > 0))
 154  
             {
 155  0
                 str += (object.getIdentifier() + " = " + object.toString() + "\n");
 156  
             }
 157  
         }
 158  0
         return str;
 159  
     }
 160  
 
 161  
     /**
 162  
      * Sets all objects of identifier type to value defined by <code>obj</code> argument.
 163  
      *
 164  
      * @param identifier <code>MP3Object</code> identifier
 165  
      * @param value      new datatype value
 166  
      */
 167  
     public final void setObjectValue(String identifier, Object value)
 168  
     {
 169  
         AbstractDataType object;
 170  2927
         Iterator<AbstractDataType> iterator = objectList.listIterator();
 171  10495
         while (iterator.hasNext())
 172  
         {
 173  7568
             object = iterator.next();
 174  7568
             if (object.getIdentifier().equals(identifier))
 175  
             {
 176  2895
                 object.setValue(value);
 177  
             }
 178  
         }
 179  2927
     }
 180  
 
 181  
     /**
 182  
      * Returns the value of the datatype with the specified
 183  
      * <code>identifier</code>
 184  
      *
 185  
      * @param identifier
 186  
      * @return the value of the dattype with the specified
 187  
      *         <code>identifier</code>
 188  
      */
 189  
     public final Object getObjectValue(String identifier)
 190  
     {
 191  1342
         return getObject(identifier).getValue();
 192  
     }
 193  
 
 194  
     /**
 195  
      * Returns the datatype with the specified
 196  
      * <code>identifier</code>
 197  
      *
 198  
      * @param identifier
 199  
      * @return the datatype with the specified
 200  
      *         <code>identifier</code>
 201  
      */
 202  
     public final AbstractDataType getObject(String identifier)
 203  
     {
 204  8071
         AbstractDataType object = null;
 205  8071
         Iterator<AbstractDataType> iterator = objectList.listIterator();
 206  11641
         while (iterator.hasNext())
 207  
         {
 208  11621
             object = iterator.next();
 209  11621
             if (object.getIdentifier().equals(identifier))
 210  
             {
 211  8051
                 return object;
 212  
             }
 213  
         }
 214  20
         return null;
 215  
     }
 216  
 
 217  
     /**
 218  
      * Returns the size in bytes of this fragmentbody
 219  
      *
 220  
      * @return estimated size in bytes of this datatype
 221  
      */
 222  
     public int getSize()
 223  
     {
 224  0
         int size = 0;
 225  
         AbstractDataType object;
 226  0
         Iterator<AbstractDataType> iterator = objectList.listIterator();
 227  0
         while (iterator.hasNext())
 228  
         {
 229  0
             object = iterator.next();
 230  0
             size += object.getSize();
 231  
         }
 232  0
         return size;
 233  
     }
 234  
 
 235  
     /**
 236  
      * Returns true if this instance and its entire DataType
 237  
      * array list is a subset of the argument. This class is a subset if it is
 238  
      * the same class as the argument.
 239  
      *
 240  
      * @param obj datatype to determine subset of
 241  
      * @return true if this instance and its entire datatype array list is a
 242  
      *         subset of the argument.
 243  
      */
 244  
     public boolean isSubsetOf(Object obj)
 245  
     {
 246  0
         if ((obj instanceof AbstractTagFrameBody) == false)
 247  
         {
 248  0
             return false;
 249  
         }
 250  0
         ArrayList<AbstractDataType> superset = ((AbstractTagFrameBody) obj).objectList;
 251  0
         for (Object anObjectList : objectList)
 252  
         {
 253  0
             if (((AbstractDataType) anObjectList).getValue() != null)
 254  
             {
 255  0
                 if (superset.contains(anObjectList) == false)
 256  
                 {
 257  0
                     return false;
 258  
                 }
 259  
             }
 260  
         }
 261  0
         return true;
 262  
     }
 263  
 
 264  
     /**
 265  
      * Returns true if this datatype and its entire DataType array
 266  
      * list equals the argument. This datatype is equal to the argument if they
 267  
      * are the same class.
 268  
      *
 269  
      * @param obj datatype to determine equality of
 270  
      * @return true if this datatype and its entire <code>MP3Object</code> array
 271  
      *         list equals the argument.
 272  
      */
 273  
     public boolean equals(Object obj)
 274  
     {
 275  1
         if ((obj instanceof AbstractTagFrameBody) == false)
 276  
         {
 277  0
             return false;
 278  
         }
 279  1
         AbstractTagFrameBody object = (AbstractTagFrameBody) obj;
 280  1
         if (this.objectList.equals(object.objectList) == false)
 281  
         {
 282  0
             return false;
 283  
         }
 284  1
         return super.equals(obj);
 285  
     }
 286  
 
 287  
     /**
 288  
      * Returns an iterator of the DataType list.
 289  
      *
 290  
      * @return iterator of the DataType list.
 291  
      */
 292  
     public Iterator iterator()
 293  
     {
 294  0
         return objectList.iterator();
 295  
     }
 296  
 
 297  
 
 298  
     /**
 299  
      * Return brief description of FrameBody
 300  
      *
 301  
      * @return brief description of FrameBody
 302  
      */
 303  
     public String toString()
 304  
     {
 305  0
         return getBriefDescription();
 306  
     }
 307  
 
 308  
 
 309  
     /**
 310  
      * Create the list of Datatypes that this body
 311  
      * expects in the correct order This method needs to be implemented by concrete subclasses
 312  
      */
 313  
     protected abstract void setupObjectList();
 314  
 
 315  
     /**
 316  
      * Get Reference to header
 317  
      *
 318  
      * @return
 319  
      */
 320  
     public AbstractTagFrame getHeader()
 321  
     {
 322  1016
         return header;
 323  
     }
 324  
 
 325  
     /**
 326  
      * Set header
 327  
      *
 328  
      * @param header
 329  
      */
 330  
     public void setHeader(AbstractTagFrame header)
 331  
     {
 332  4218
         this.header = header;
 333  4218
     }
 334  
 }