Coverage Report - org.jaudiotagger.tag.datatype.AbstractDataType
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractDataType
55%
61/109
30%
34/110
6
 
 1  
 /**
 2  
  *  @author : Paul Taylor
 3  
  *  @author : Eric Farng
 4  
  *
 5  
  *  Version @version:$Id: AbstractDataType.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  
  *
 22  
  */
 23  
 package org.jaudiotagger.tag.datatype;
 24  
 
 25  
 import org.jaudiotagger.audio.mp3.MP3File;
 26  
 import org.jaudiotagger.tag.InvalidDataTypeException;
 27  
 import org.jaudiotagger.tag.id3.AbstractTagFrameBody;
 28  
 
 29  
 import java.util.Arrays;
 30  
 import java.util.logging.Logger;
 31  
 
 32  
 /**
 33  
  * Represents a field/data type that can be held within a frames body, these map loosely onto
 34  
  * Section 4. ID3v2 frame overview at http://www.id3.org/id3v2.4.0-structure.txt
 35  
  */
 36  
 public abstract class AbstractDataType
 37  
 {
 38  
     protected static final String TYPE_ELEMENT = "element";
 39  
 
 40  
     //Logger
 41  4
     public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.datatype");
 42  
 
 43  
     /**
 44  
      * Holds the data
 45  
      */
 46  37013
     protected Object value = null;
 47  
 
 48  
     /**
 49  
      * Holds the key such as "Text" or "PictureType", the naming of keys are fairly arbitary but are intended
 50  
      * to make it easier to for the developer, the keys themseleves are not written to the tag.
 51  
      */
 52  37013
     protected String identifier = "";
 53  
 
 54  
     /**
 55  
      * Holds the calling body, allows an datatype to query other objects in the
 56  
      * body such as the Text Encoding of the frame
 57  
      */
 58  37013
     protected AbstractTagFrameBody frameBody = null;
 59  
 
 60  
     /**
 61  
      * Holds the size of the data in file when read/written
 62  
      */
 63  
     protected int size;
 64  
 
 65  
     /**
 66  
      * Construct an abstract datatype identified by identifier and linked to a framebody without setting
 67  
      * an initial value.
 68  
      *
 69  
      * @param identifier to allow retrieval of this datatype by name from framebody
 70  
      * @param frameBody  that the dataype is associated with
 71  
      */
 72  
     protected AbstractDataType(String identifier, AbstractTagFrameBody frameBody)
 73  23613
     {
 74  23613
         this.identifier = identifier;
 75  23613
         this.frameBody = frameBody;
 76  23613
     }
 77  
 
 78  
     /**
 79  
      * Construct an abstract datatype identified by identifier and linked to a framebody initilised with a value
 80  
      *
 81  
      * @param identifier to allow retrieval of this datatype by name from framebody
 82  
      * @param frameBody  that the dataype is associated with
 83  
      * @param value      of this DataType
 84  
      */
 85  
     protected AbstractDataType(String identifier, AbstractTagFrameBody frameBody, Object value)
 86  8
     {
 87  8
         this.identifier = identifier;
 88  8
         this.frameBody = frameBody;
 89  8
         setValue(value);
 90  8
     }
 91  
 
 92  
     /**
 93  
      * This is used by subclasses, to clone the data within the copyObject
 94  
      * <p/>
 95  
      * TODO:It seems to be missing some of the more complex value types.
 96  
      * @param copyObject
 97  
      */
 98  
     public AbstractDataType(AbstractDataType copyObject)
 99  13392
     {
 100  
         // no copy constructor in super class
 101  13392
         this.identifier = copyObject.identifier;
 102  13392
         if (copyObject.value == null)
 103  
         {
 104  104
             this.value = null;
 105  
         }
 106  13288
         else if (copyObject.value instanceof String)
 107  
         {
 108  7163
             this.value = copyObject.value;
 109  
         }
 110  6125
         else if (copyObject.value instanceof Boolean)
 111  
         {
 112  0
             this.value = copyObject.value;
 113  
         }
 114  6125
         else if (copyObject.value instanceof Byte)
 115  
         {
 116  0
             this.value = copyObject.value;
 117  
         }
 118  6125
         else if (copyObject.value instanceof Character)
 119  
         {
 120  0
             this.value = copyObject.value;
 121  
         }
 122  6125
         else if (copyObject.value instanceof Double)
 123  
         {
 124  0
             this.value = copyObject.value;
 125  
         }
 126  6125
         else if (copyObject.value instanceof Float)
 127  
         {
 128  0
             this.value = copyObject.value;
 129  
         }
 130  6125
         else if (copyObject.value instanceof Integer)
 131  
         {
 132  0
             this.value = copyObject.value;
 133  
         }
 134  6125
         else if (copyObject.value instanceof Long)
 135  
         {
 136  5429
             this.value = copyObject.value;
 137  
         }
 138  696
         else if (copyObject.value instanceof Short)
 139  
         {
 140  0
             this.value = copyObject.value;
 141  
         }
 142  696
         else if(copyObject.value instanceof MultipleTextEncodedStringNullTerminated.Values)
 143  
         {
 144  1
             this.value = copyObject.value;
 145  
         }
 146  695
         else if(copyObject.value instanceof PartOfSet.PartOfSetValue)
 147  
         {
 148  434
             this.value = copyObject.value;
 149  
         }
 150  261
         else if (copyObject.value instanceof boolean[])
 151  
         {
 152  0
             this.value = ((boolean[]) copyObject.value).clone();
 153  
         }
 154  261
         else if (copyObject.value instanceof byte[])
 155  
         {
 156  261
             this.value = ((byte[]) copyObject.value).clone();
 157  
         }
 158  0
         else if (copyObject.value instanceof char[])
 159  
         {
 160  0
             this.value = ((char[]) copyObject.value).clone();
 161  
         }
 162  0
         else if (copyObject.value instanceof double[])
 163  
         {
 164  0
             this.value = ((double[]) copyObject.value).clone();
 165  
         }
 166  0
         else if (copyObject.value instanceof float[])
 167  
         {
 168  0
             this.value = ((float[]) copyObject.value).clone();
 169  
         }
 170  0
         else if (copyObject.value instanceof int[])
 171  
         {
 172  0
             this.value = ((int[]) copyObject.value).clone();
 173  
         }
 174  0
         else if (copyObject.value instanceof long[])
 175  
         {
 176  0
             this.value = ((long[]) copyObject.value).clone();
 177  
         }
 178  0
         else if (copyObject.value instanceof short[])
 179  
         {
 180  0
             this.value = ((short[]) copyObject.value).clone();
 181  
         }
 182  0
         else if (copyObject.value instanceof Object[])
 183  
         {
 184  0
             this.value = ((Object[]) copyObject.value).clone();
 185  
         }
 186  
         else
 187  
         {
 188  0
             throw new UnsupportedOperationException("Unable to create copy of class " + copyObject.getClass());
 189  
         }
 190  13392
     }
 191  
 
 192  
     /**
 193  
      * Set the framebody that this datatype is associated with
 194  
      *
 195  
      * @param frameBody
 196  
      */
 197  
     public void setBody(AbstractTagFrameBody frameBody)
 198  
     {
 199  13392
         this.frameBody = frameBody;
 200  13392
     }
 201  
 
 202  
     /**
 203  
      * Get the framebody associated with this datatype
 204  
      *
 205  
      * @return the framebody that this datatype is associated with
 206  
      */
 207  
     public AbstractTagFrameBody getBody()
 208  
     {
 209  18526
         return frameBody;
 210  
     }
 211  
 
 212  
     /**
 213  
      * Return the key as declared by the frame bodies datatype list
 214  
      *
 215  
      * @return the key used to reference this datatype from a framebody
 216  
      */
 217  
     public String getIdentifier()
 218  
     {
 219  90901
         return identifier;
 220  
     }
 221  
 
 222  
     /**
 223  
      * Set the value held by this datatype, this is used typically used when the
 224  
      * user wants to modify the value in an existing frame.
 225  
      *
 226  
      * @param value
 227  
      */
 228  
     public void setValue(Object value)
 229  
     {
 230  5280
         this.value = value;
 231  5280
     }
 232  
 
 233  
     /**
 234  
      * Get value held by this Object
 235  
      *
 236  
      * @return value held by this Object
 237  
      */
 238  
     public Object getValue()
 239  
     {
 240  31438
         return value;
 241  
     }
 242  
 
 243  
     /**
 244  
      * Simplified wrapper for reading bytes from file into Object.
 245  
      * Used for reading Strings, this class should be overridden
 246  
      * for non String Objects
 247  
      *
 248  
      * @param arr
 249  
      * @throws org.jaudiotagger.tag.InvalidDataTypeException
 250  
      */
 251  
     final public void readByteArray(byte[] arr) throws InvalidDataTypeException
 252  
     {
 253  0
         readByteArray(arr, 0);
 254  0
     }
 255  
 
 256  
     /**
 257  
      * This defines the size in bytes of the datatype being
 258  
      * held when read/written to file.
 259  
      *
 260  
      * @return the size in bytes of the datatype
 261  
      */
 262  
     abstract public int getSize();
 263  
 
 264  
     /**
 265  
      * @param obj
 266  
      * @return whether this and obj are deemed equivalent
 267  
      */
 268  
     public boolean equals(Object obj)
 269  
     {
 270  16
         if (!(obj instanceof AbstractDataType))
 271  
         {
 272  0
             return false;
 273  
         }
 274  16
         AbstractDataType object = (AbstractDataType) obj;
 275  16
         if (!this.identifier.equals(object.identifier))
 276  
         {
 277  0
             return false;
 278  
         }
 279  16
         if ((this.value == null) && (object.value == null))
 280  
         {
 281  0
             return true;
 282  
         }
 283  16
         else if ((this.value == null) || (object.value == null))
 284  
         {
 285  0
             return false;
 286  
         }
 287  
         // boolean[]
 288  16
         if (this.value instanceof boolean[] && object.value instanceof boolean[])
 289  
         {
 290  0
             if (!Arrays.equals((boolean[]) this.value, (boolean[]) object.value))
 291  
             {
 292  0
                 return false;
 293  
             }
 294  
             // byte[]
 295  
         }
 296  16
         else if (this.value instanceof byte[] && object.value instanceof byte[])
 297  
         {
 298  0
             if (!Arrays.equals((byte[]) this.value, (byte[]) object.value))
 299  
             {
 300  0
                 return false;
 301  
             }
 302  
             // char[]
 303  
         }
 304  16
         else if (this.value instanceof char[] && object.value instanceof char[])
 305  
         {
 306  0
             if (!Arrays.equals((char[]) this.value, (char[]) object.value))
 307  
             {
 308  0
                 return false;
 309  
             }
 310  
             // double[]
 311  
         }
 312  16
         else if (this.value instanceof double[] && object.value instanceof double[])
 313  
         {
 314  0
             if (!Arrays.equals((double[]) this.value, (double[]) object.value))
 315  
             {
 316  0
                 return false;
 317  
             }
 318  
             // float[]
 319  
         }
 320  16
         else if (this.value instanceof float[] && object.value instanceof float[])
 321  
         {
 322  0
             if (!Arrays.equals((float[]) this.value, (float[]) object.value))
 323  
             {
 324  0
                 return false;
 325  
             }
 326  
             // int[]
 327  
         }
 328  16
         else if (this.value instanceof int[] && object.value instanceof int[])
 329  
         {
 330  0
             if (!Arrays.equals((int[]) this.value, (int[]) object.value))
 331  
             {
 332  0
                 return false;
 333  
             }
 334  
             // long[]
 335  
         }
 336  16
         else if (this.value instanceof long[] && object.value instanceof long[])
 337  
         {
 338  0
             if (!Arrays.equals((long[]) this.value, (long[]) object.value))
 339  
             {
 340  0
                 return false;
 341  
             }
 342  
             // Object[]
 343  
         }
 344  16
         else if (this.value instanceof Object[] && object.value instanceof Object[])
 345  
         {
 346  0
             if (!Arrays.equals((Object[]) this.value, (Object[]) object.value))
 347  
             {
 348  0
                 return false;
 349  
             }
 350  
             // short[]
 351  
         }
 352  16
         else if (this.value instanceof short[] && object.value instanceof short[])
 353  
         {
 354  0
             if (!Arrays.equals((short[]) this.value, (short[]) object.value))
 355  
             {
 356  0
                 return false;
 357  
             }
 358  
         }
 359  16
         else if (!this.value.equals(object.value))
 360  
         {
 361  0
             return false;
 362  
         }
 363  16
         return true;
 364  
     }
 365  
 
 366  
     /**
 367  
      * This is the starting point for reading bytes from the file into the ID3 datatype
 368  
      * starting at offset.
 369  
      * This class must be overridden
 370  
      *
 371  
      * @param arr
 372  
      * @param offset
 373  
      * @throws org.jaudiotagger.tag.InvalidDataTypeException
 374  
      */
 375  
     public abstract void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException;
 376  
 
 377  
 
 378  
     /**
 379  
      * Starting point write ID3 Datatype back to array of bytes.
 380  
      * This class must be overridden.
 381  
      *
 382  
      * @return the array of bytes representing this datatype that should be written to file
 383  
      */
 384  
     public abstract byte[] writeByteArray();
 385  
 
 386  
     /**
 387  
      * Return String Representation of Datatype     *
 388  
      */
 389  
     public void createStructure()
 390  
     {
 391  1092
         MP3File.getStructureFormatter().addElement(identifier, getValue().toString());
 392  1092
     }
 393  
 
 394  
 }