Coverage Report - org.jaudiotagger.tag.id3.AbstractTagFrameBody
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractTagFrameBody
64%
41/64
50%
20/40
2.333
 
 1  
 /**
 2  
  *  @author : Paul Taylor
 3  
  *  @author : Eric Farng
 4  
  *
 5  
  *  Version @version:$Id: AbstractTagFrameBody.java 836 2009-11-12 15:44:07Z paultaylor $
 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  15161
     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  23787
         AbstractDataType o = getObject(DataTypes.OBJ_TEXT_ENCODING);
 72  
 
 73  23787
         if (o != null)
 74  
         {
 75  23707
             Long encoding = (Long) (o.getValue());
 76  23707
             return encoding.byteValue();
 77  
         }
 78  
         else
 79  
         {
 80  80
             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  5594
         setObjectValue(DataTypes.OBJ_TEXT_ENCODING, textEncoding);
 93  5594
     }
 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  9643
     {
 102  9643
         setupObjectList();
 103  9643
     }
 104  
 
 105  
     /**
 106  
      * Copy Constructor for fragment body. Copies all objects in the
 107  
      * Object Iterator with data.
 108  
      * @param copyObject
 109  
      */
 110  
     protected AbstractTagFrameBody(AbstractTagFrameBody copyObject)
 111  5518
     {
 112  
         AbstractDataType newObject;
 113  18910
         for (int i = 0; i < copyObject.objectList.size(); i++)
 114  
         {
 115  13392
             newObject = (AbstractDataType) ID3Tags.copyObject(copyObject.objectList.get(i));
 116  13392
             newObject.setBody(this);
 117  13392
             this.objectList.add(newObject);
 118  
         }
 119  5518
     }
 120  
 
 121  
 
 122  
     /**
 123  
      * This method calls <code>toString</code> for all it's objects and appends
 124  
      * them without any newline characters.
 125  
      *
 126  
      * @return brief description string
 127  
      */
 128  
     public String getBriefDescription()
 129  
     {
 130  8
         String str = "";
 131  8
         for (AbstractDataType object : objectList)
 132  
         {
 133  16
             if ((object.toString() != null) && (object.toString().length() > 0))
 134  
             {
 135  8
                 str += (object.getIdentifier() + "=\"" + object.toString() + "\"; ");
 136  
             }
 137  
         }
 138  8
         return str;
 139  
     }
 140  
 
 141  
 
 142  
     /**
 143  
      * This method calls <code>toString</code> for all it's objects and appends
 144  
      * them. It contains new line characters and is more suited for display
 145  
      * purposes
 146  
      *
 147  
      * @return formatted description string
 148  
      */
 149  
     public final String getLongDescription()
 150  
     {
 151  0
         String str = "";
 152  0
         for (AbstractDataType object : objectList)
 153  
         {
 154  0
             if ((object.toString() != null) && (object.toString().length() > 0))
 155  
             {
 156  0
                 str += (object.getIdentifier() + " = " + object.toString() + "\n");
 157  
             }
 158  
         }
 159  0
         return str;
 160  
     }
 161  
 
 162  
     /**
 163  
      * Sets all objects of identifier type to value defined by <code>obj</code> argument.
 164  
      *
 165  
      * @param identifier <code>MP3Object</code> identifier
 166  
      * @param value      new datatype value
 167  
      */
 168  
     public final void setObjectValue(String identifier, Object value)
 169  
     {
 170  
         AbstractDataType object;
 171  14367
         Iterator<AbstractDataType> iterator = objectList.listIterator();
 172  51506
         while (iterator.hasNext())
 173  
         {
 174  37139
             object = iterator.next();
 175  37139
             if (object.getIdentifier().equals(identifier))
 176  
             {
 177  14239
                 object.setValue(value);
 178  
             }
 179  
         }
 180  14367
     }
 181  
 
 182  
     /**
 183  
      * Returns the value of the datatype with the specified
 184  
      * <code>identifier</code>
 185  
      *
 186  
      * @param identifier
 187  
      * @return the value of the dattype with the specified
 188  
      *         <code>identifier</code>
 189  
      */
 190  
     public final Object getObjectValue(String identifier)
 191  
     {
 192  7129
         return getObject(identifier).getValue();
 193  
     }
 194  
 
 195  
     /**
 196  
      * Returns the datatype with the specified
 197  
      * <code>identifier</code>
 198  
      *
 199  
      * @param identifier
 200  
      * @return the datatype with the specified
 201  
      *         <code>identifier</code>
 202  
      */
 203  
     public final AbstractDataType getObject(String identifier)
 204  
     {
 205  
         AbstractDataType object;
 206  36716
         Iterator<AbstractDataType> iterator = objectList.listIterator();
 207  53561
         while (iterator.hasNext())
 208  
         {
 209  53481
             object = iterator.next();
 210  53481
             if (object.getIdentifier().equals(identifier))
 211  
             {
 212  36636
                 return object;
 213  
             }
 214  
         }
 215  80
         return null;
 216  
     }
 217  
 
 218  
     /**
 219  
      * Returns the size in bytes of this fragmentbody
 220  
      *
 221  
      * @return estimated size in bytes of this datatype
 222  
      */
 223  
     public int getSize()
 224  
     {
 225  0
         int size = 0;
 226  
         AbstractDataType object;
 227  0
         Iterator<AbstractDataType> iterator = objectList.listIterator();
 228  0
         while (iterator.hasNext())
 229  
         {
 230  0
             object = iterator.next();
 231  0
             size += object.getSize();
 232  
         }
 233  0
         return size;
 234  
     }
 235  
 
 236  
     /**
 237  
      * Returns true if this instance and its entire DataType
 238  
      * array list is a subset of the argument. This class is a subset if it is
 239  
      * the same class as the argument.
 240  
      *
 241  
      * @param obj datatype to determine subset of
 242  
      * @return true if this instance and its entire datatype array list is a
 243  
      *         subset of the argument.
 244  
      */
 245  
     public boolean isSubsetOf(Object obj)
 246  
     {
 247  0
         if (!(obj instanceof AbstractTagFrameBody))
 248  
         {
 249  0
             return false;
 250  
         }
 251  0
         ArrayList<AbstractDataType> superset = ((AbstractTagFrameBody) obj).objectList;
 252  0
         for (AbstractDataType anObjectList : objectList)
 253  
         {
 254  0
             if (anObjectList.getValue() != null)
 255  
             {
 256  0
                 if (!superset.contains(anObjectList))
 257  
                 {
 258  0
                     return false;
 259  
                 }
 260  
             }
 261  
         }
 262  0
         return true;
 263  
     }
 264  
 
 265  
     /**
 266  
      * Returns true if this datatype and its entire DataType array
 267  
      * list equals the argument. This datatype is equal to the argument if they
 268  
      * are the same class.
 269  
      *
 270  
      * @param obj datatype to determine equality of
 271  
      * @return true if this datatype and its entire <code>MP3Object</code> array
 272  
      *         list equals the argument.
 273  
      */
 274  
     public boolean equals(Object obj)
 275  
     {
 276  4
         if (!(obj instanceof AbstractTagFrameBody))
 277  
         {
 278  0
             return false;
 279  
         }
 280  4
         AbstractTagFrameBody object = (AbstractTagFrameBody) obj;
 281  4
         return this.objectList.equals(object.objectList) && super.equals(obj);
 282  
     }
 283  
 
 284  
     /**
 285  
      * Returns an iterator of the DataType list.
 286  
      *
 287  
      * @return iterator of the DataType list.
 288  
      */
 289  
     public Iterator iterator()
 290  
     {
 291  0
         return objectList.iterator();
 292  
     }
 293  
 
 294  
 
 295  
     /**
 296  
      * Return brief description of FrameBody
 297  
      *
 298  
      * @return brief description of FrameBody
 299  
      */
 300  
     public String toString()
 301  
     {
 302  0
         return getBriefDescription();
 303  
     }
 304  
 
 305  
 
 306  
     /**
 307  
      * Create the list of Datatypes that this body
 308  
      * expects in the correct order This method needs to be implemented by concrete subclasses
 309  
      */
 310  
     protected abstract void setupObjectList();
 311  
 
 312  
     /**
 313  
      * Get Reference to header
 314  
      *
 315  
      * @return
 316  
      */
 317  
     public AbstractTagFrame getHeader()
 318  
     {
 319  4368
         return header;
 320  
     }
 321  
 
 322  
     /**
 323  
      * Set header
 324  
      *
 325  
      * @param header
 326  
      */
 327  
     public void setHeader(AbstractTagFrame header)
 328  
     {
 329  19485
         this.header = header;
 330  19485
     }
 331  
 }