Coverage Report - org.jaudiotagger.tag.datatype.AbstractDataType
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractDataType
50%
54/107
30%
32/108
5.143
 
 1  
 /**
 2  
  *  @author : Paul Taylor
 3  
  *  @author : Eric Farng
 4  
  *
 5  
  *  Version @version:$Id: AbstractDataType.java,v 1.15 2008/11/12 16:41:38 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  
  *
 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 extends java.lang.Object
 37  
 {
 38  
     protected static final String TYPE_ELEMENT = "element";
 39  
 
 40  
     //Logger
 41  66
     public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.datatype");
 42  
 
 43  
     /**
 44  
      * Holds the data
 45  
      */
 46  8150
     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  8150
     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  8150
     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  5257
     {
 74  5257
         this.identifier = identifier;
 75  5257
         this.frameBody = frameBody;
 76  5257
     }
 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  0
     {
 87  0
         this.identifier = identifier;
 88  0
         this.frameBody = frameBody;
 89  0
         setValue(value);
 90  0
     }
 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  
      */
 97  
     public AbstractDataType(AbstractDataType copyObject)
 98  2893
     {
 99  
         // no copy constructor in super class
 100  2893
         this.identifier = new String(copyObject.identifier);
 101  2893
         if (copyObject.value == null)
 102  
         {
 103  19
             this.value = null;
 104  
         }
 105  2874
         else if (copyObject.value instanceof String)
 106  
         {
 107  1645
             this.value = new String((String) copyObject.value);
 108  
         }
 109  1229
         else if (copyObject.value instanceof Boolean)
 110  
         {
 111  0
             this.value = copyObject.value;
 112  
         }
 113  1229
         else if (copyObject.value instanceof Byte)
 114  
         {
 115  0
             this.value = copyObject.value;
 116  
         }
 117  1229
         else if (copyObject.value instanceof Character)
 118  
         {
 119  0
             this.value = copyObject.value;
 120  
         }
 121  1229
         else if (copyObject.value instanceof Double)
 122  
         {
 123  0
             this.value = copyObject.value;
 124  
         }
 125  1229
         else if (copyObject.value instanceof Float)
 126  
         {
 127  0
             this.value = copyObject.value;
 128  
         }
 129  1229
         else if (copyObject.value instanceof Integer)
 130  
         {
 131  0
             this.value = copyObject.value;
 132  
         }
 133  1229
         else if (copyObject.value instanceof Long)
 134  
         {
 135  1154
             this.value = copyObject.value;
 136  
         }
 137  75
         else if (copyObject.value instanceof Short)
 138  
         {
 139  0
             this.value = copyObject.value;
 140  
         }
 141  75
         else if(copyObject.value instanceof MultipleTextEncodedStringNullTerminated.Values)
 142  
         {
 143  1
             this.value = ((MultipleTextEncodedStringNullTerminated.Values) copyObject.value);
 144  
         }
 145  74
         else if (copyObject.value instanceof boolean[])
 146  
         {
 147  0
             this.value = ((boolean[]) copyObject.value).clone();
 148  
         }
 149  74
         else if (copyObject.value instanceof byte[])
 150  
         {
 151  74
             this.value = ((byte[]) copyObject.value).clone();
 152  
         }
 153  0
         else if (copyObject.value instanceof char[])
 154  
         {
 155  0
             this.value = ((char[]) copyObject.value).clone();
 156  
         }
 157  0
         else if (copyObject.value instanceof double[])
 158  
         {
 159  0
             this.value = ((double[]) copyObject.value).clone();
 160  
         }
 161  0
         else if (copyObject.value instanceof float[])
 162  
         {
 163  0
             this.value = ((float[]) copyObject.value).clone();
 164  
         }
 165  0
         else if (copyObject.value instanceof int[])
 166  
         {
 167  0
             this.value = ((int[]) copyObject.value).clone();
 168  
         }
 169  0
         else if (copyObject.value instanceof long[])
 170  
         {
 171  0
             this.value = ((long[]) copyObject.value).clone();
 172  
         }
 173  0
         else if (copyObject.value instanceof short[])
 174  
         {
 175  0
             this.value = ((short[]) copyObject.value).clone();
 176  
         }
 177  0
         else if (copyObject.value instanceof Object[])
 178  
         {
 179  0
             this.value = ((Object[]) copyObject.value).clone();
 180  
         }
 181  
         else
 182  
         {
 183  0
             throw new UnsupportedOperationException("Unable to create copy of class " + copyObject.getClass());
 184  
         }
 185  2893
     }
 186  
 
 187  
     /**
 188  
      * Set the framebody that this datatype is associated with
 189  
      *
 190  
      * @param frameBody
 191  
      */
 192  
     public void setBody(AbstractTagFrameBody frameBody)
 193  
     {
 194  2893
         this.frameBody = frameBody;
 195  2893
     }
 196  
 
 197  
     /**
 198  
      * Get the framebody associated with this datatype
 199  
      *
 200  
      * @return the framebody that this datatype is associated with
 201  
      */
 202  
     public AbstractTagFrameBody getBody()
 203  
     {
 204  4196
         return frameBody;
 205  
     }
 206  
 
 207  
     /**
 208  
      * Return the key as declared by the frame bodies datatype list
 209  
      *
 210  
      * @return the key used to reference this datatype from a framebody
 211  
      */
 212  
     public String getIdentifier()
 213  
     {
 214  19261
         return identifier;
 215  
     }
 216  
 
 217  
     /**
 218  
      * Set the value held by this datatype, this is used typically used when the
 219  
      * user wants to modify the value in an existing frame.
 220  
      *
 221  
      * @param value
 222  
      */
 223  
     public void setValue(Object value)
 224  
     {
 225  1029
         this.value = value;
 226  1029
     }
 227  
 
 228  
     /**
 229  
      * Get value held by this Object
 230  
      *
 231  
      * @return value held by this Object
 232  
      */
 233  
     public Object getValue()
 234  
     {
 235  6946
         return value;
 236  
     }
 237  
 
 238  
     /**
 239  
      * Simplified wrapper for reading bytes from file into Object.
 240  
      * Used for reading Strings, this class should be overridden
 241  
      * for non String Objects
 242  
      *
 243  
      * @param arr
 244  
      */
 245  
     final public void readByteArray(byte[] arr) throws InvalidDataTypeException
 246  
     {
 247  0
         readByteArray(arr, 0);
 248  0
     }
 249  
 
 250  
     /**
 251  
      * This defines the size in bytes of the datatype being
 252  
      * held when read/written to file.
 253  
      *
 254  
      * @return the size in bytes of the datatype
 255  
      */
 256  
     abstract public int getSize();
 257  
 
 258  
     /**
 259  
      * @param obj
 260  
      * @return whether this and obj are deemed equivalent
 261  
      */
 262  
     public boolean equals(Object obj)
 263  
     {
 264  4
         if ((obj instanceof AbstractDataType) == false)
 265  
         {
 266  0
             return false;
 267  
         }
 268  4
         AbstractDataType object = (AbstractDataType) obj;
 269  4
         if (this.identifier.equals(object.identifier) == false)
 270  
         {
 271  0
             return false;
 272  
         }
 273  4
         if ((this.value == null) && (object.value == null))
 274  
         {
 275  0
             return true;
 276  
         }
 277  4
         else if ((this.value == null) || (object.value == null))
 278  
         {
 279  0
             return false;
 280  
         }
 281  
         // boolean[]
 282  4
         if (this.value instanceof boolean[] && object.value instanceof boolean[])
 283  
         {
 284  0
             if (Arrays.equals((boolean[]) this.value, (boolean[]) object.value) == false)
 285  
             {
 286  0
                 return false;
 287  
             }
 288  
             // byte[]
 289  
         }
 290  4
         else if (this.value instanceof byte[] && object.value instanceof byte[])
 291  
         {
 292  0
             if (Arrays.equals((byte[]) this.value, (byte[]) object.value) == false)
 293  
             {
 294  0
                 return false;
 295  
             }
 296  
             // char[]
 297  
         }
 298  4
         else if (this.value instanceof char[] && object.value instanceof char[])
 299  
         {
 300  0
             if (Arrays.equals((char[]) this.value, (char[]) object.value) == false)
 301  
             {
 302  0
                 return false;
 303  
             }
 304  
             // double[]
 305  
         }
 306  4
         else if (this.value instanceof double[] && object.value instanceof double[])
 307  
         {
 308  0
             if (Arrays.equals((double[]) this.value, (double[]) object.value) == false)
 309  
             {
 310  0
                 return false;
 311  
             }
 312  
             // float[]
 313  
         }
 314  4
         else if (this.value instanceof float[] && object.value instanceof float[])
 315  
         {
 316  0
             if (Arrays.equals((float[]) this.value, (float[]) object.value) == false)
 317  
             {
 318  0
                 return false;
 319  
             }
 320  
             // int[]
 321  
         }
 322  4
         else if (this.value instanceof int[] && object.value instanceof int[])
 323  
         {
 324  0
             if (Arrays.equals((int[]) this.value, (int[]) object.value) == false)
 325  
             {
 326  0
                 return false;
 327  
             }
 328  
             // long[]
 329  
         }
 330  4
         else if (this.value instanceof long[] && object.value instanceof long[])
 331  
         {
 332  0
             if (Arrays.equals((long[]) this.value, (long[]) object.value) == false)
 333  
             {
 334  0
                 return false;
 335  
             }
 336  
             // Object[]
 337  
         }
 338  4
         else if (this.value instanceof Object[] && object.value instanceof Object[])
 339  
         {
 340  0
             if (Arrays.equals((Object[]) this.value, (Object[]) object.value) == false)
 341  
             {
 342  0
                 return false;
 343  
             }
 344  
             // short[]
 345  
         }
 346  4
         else if (this.value instanceof short[] && object.value instanceof short[])
 347  
         {
 348  0
             if (Arrays.equals((short[]) this.value, (short[]) object.value) == false)
 349  
             {
 350  0
                 return false;
 351  
             }
 352  
         }
 353  4
         else if (this.value.equals(object.value) == false)
 354  
         {
 355  0
             return false;
 356  
         }
 357  4
         return true;
 358  
     }
 359  
 
 360  
     /**
 361  
      * This is the starting point for reading bytes from the file into the ID3 datatype
 362  
      * starting at offset.
 363  
      * This class must be overridden
 364  
      *
 365  
      * @param arr
 366  
      * @param offset
 367  
      */
 368  
     public abstract void readByteArray(byte[] arr, int offset) throws InvalidDataTypeException;
 369  
 
 370  
 
 371  
     /**
 372  
      * Starting point write ID3 Datatype back to array of bytes.
 373  
      * This class must be overridden.
 374  
      *
 375  
      * @return the array of bytes representing this datatype that should be written to file
 376  
      */
 377  
     public abstract byte[] writeByteArray();
 378  
 
 379  
     /**
 380  
      * Return String Representation of Datatype     *
 381  
      */
 382  
     public void createStructure()
 383  
     {
 384  249
         MP3File.getStructureFormatter().addElement(identifier, getValue().toString());
 385  249
     }
 386  
 
 387  
 }