Coverage Report - org.jaudiotagger.tag.mp4.Mp4TagField
 
Classes in this File Line Coverage Branch Coverage Complexity
Mp4TagField
76%
30/39
100%
14/14
1.923
 
 1  
 /*
 2  
  * Entagged Audio Tag library
 3  
  * Copyright (c) 2003-2005 RaphaĆ«l Slinckx <raphael@slinckx.net>
 4  
  * 
 5  
  * This library is free software; you can redistribute it and/or
 6  
  * modify it under the terms of the GNU Lesser General Public
 7  
  * License as published by the Free Software Foundation; either
 8  
  * version 2.1 of the License, or (at your option) any later version.
 9  
  *  
 10  
  * This library is distributed in the hope that it will be useful,
 11  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
  * Lesser General Public License for more details. 
 14  
  * 
 15  
  * You should have received a copy of the GNU Lesser General Public
 16  
  * License along with this library; if not, write to the Free Software
 17  
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 18  
  */
 19  
 package org.jaudiotagger.tag.mp4;
 20  
 
 21  
 import org.jaudiotagger.audio.generic.Utils;
 22  
 import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader;
 23  
 import org.jaudiotagger.tag.TagField;
 24  
 import org.jaudiotagger.tag.mp4.atom.Mp4DataBox;
 25  
 import org.jaudiotagger.tag.mp4.field.Mp4FieldType;
 26  
 
 27  
 import java.io.ByteArrayOutputStream;
 28  
 import java.io.IOException;
 29  
 import java.io.UnsupportedEncodingException;
 30  
 import java.nio.ByteBuffer;
 31  
 import java.util.logging.Logger;
 32  
 
 33  
 /**
 34  
  * This abstract class represents a link between piece of data, and how it is stored as an mp4 atom
 35  
  * <p/>
 36  
  * Note there isnt a one to one correspondance between a tag field and a box because some fields are represented
 37  
  * by multiple boxes, for example many of the MusicBrainz fields use the '----' box, which in turn uses one of mean,
 38  
  * name and data box. So an instance of a tag field maps to one item of data such as 'Title', but it may have to read
 39  
  * multiple boxes to do this.   
 40  
  * <p/>
 41  
  * There are various subclasses that represent different types of fields               
 42  
  */
 43  
 public abstract class Mp4TagField implements TagField
 44  
 {
 45  
     // Logger Object
 46  4
     public static Logger logger = Logger.getLogger("org.jaudiotagger.tag.mp4");
 47  
 
 48  
 
 49  
     protected String id;
 50  
 
 51  
     //Just used by reverese dns class, so it knows the size of its aprent so it can detect end correctly
 52  
     protected Mp4BoxHeader parentHeader;
 53  
 
 54  
     protected Mp4TagField(String id)
 55  7032
     {
 56  7032
         this.id = id;
 57  7032
     }
 58  
 
 59  
     /**
 60  
      * Used by subclasses that canot identify their id until after they have been built such as ReverseDnsField
 61  
      *
 62  
      * @param data
 63  
      * @throws UnsupportedEncodingException
 64  
      */
 65  
     protected Mp4TagField(ByteBuffer data) throws UnsupportedEncodingException
 66  0
     {
 67  0
         build(data);
 68  0
     }
 69  
 
 70  
     /**
 71  
      * Used by reverese dns when reading from file, so can identify when there is a data atom
 72  
      *
 73  
      * @param parentHeader
 74  
      * @param data
 75  
      * @throws UnsupportedEncodingException
 76  
      */
 77  
     protected Mp4TagField(Mp4BoxHeader parentHeader, ByteBuffer data) throws UnsupportedEncodingException
 78  1790
     {
 79  1790
         this.parentHeader = parentHeader;
 80  1790
         build(data);
 81  1790
     }
 82  
 
 83  
     protected Mp4TagField(String id, ByteBuffer data) throws UnsupportedEncodingException
 84  
     {
 85  6076
         this(id);
 86  6076
         build(data);
 87  6076
     }
 88  
 
 89  
     /**
 90  
      * @return field identifier
 91  
      */
 92  
     public String getId()
 93  
     {
 94  30695
         return id;
 95  
     }
 96  
 
 97  
     public void isBinary(boolean b)
 98  
     {
 99  
         /* One cannot choose if an arbitrary block can be binary or not */
 100  0
     }
 101  
 
 102  
     public boolean isCommon()
 103  
     {
 104  8402
         return id.equals(Mp4FieldKey.ARTIST.getFieldName()) || id.equals(Mp4FieldKey.ALBUM.getFieldName()) || id.equals(Mp4FieldKey.TITLE.getFieldName()) || id.equals(Mp4FieldKey.TRACK.getFieldName()) || id.equals(Mp4FieldKey.DAY.getFieldName()) || id.equals(Mp4FieldKey.COMMENT.getFieldName()) || id.equals(Mp4FieldKey.GENRE.getFieldName());
 105  
     }
 106  
 
 107  
     /**
 108  
      * @return field identifier as it will be held within the file
 109  
      */
 110  
     protected byte[] getIdBytes()
 111  
     {
 112  0
         return Utils.getDefaultBytes(getId(), "ISO-8859-1");
 113  
     }
 114  
 
 115  
     /**
 116  
      * @return the data as it is held on file
 117  
      * @throws UnsupportedEncodingException
 118  
      */
 119  
     protected abstract byte[] getDataBytes() throws UnsupportedEncodingException;
 120  
 
 121  
 
 122  
     /**
 123  
      * @return the field type of this field
 124  
      */
 125  
     public abstract Mp4FieldType getFieldType();
 126  
 
 127  
     /**
 128  
      * Processes the data and sets the position of the data buffer to just after the end of this fields data
 129  
      * ready for processing next field.
 130  
      *
 131  
      * @param data
 132  
      * @throws UnsupportedEncodingException
 133  
      */
 134  
     protected abstract void build(ByteBuffer data) throws UnsupportedEncodingException;
 135  
 
 136  
     /**
 137  
      * Convert back to raw content, includes parent and data atom as views as one thing externally
 138  
      *
 139  
      * @return
 140  
      * @throws UnsupportedEncodingException
 141  
      */
 142  
     public byte[] getRawContent() throws UnsupportedEncodingException
 143  
     {
 144  2727
         logger.fine("Getting Raw data for:" + getId());
 145  
         try
 146  
         {
 147  
             //Create Data Box
 148  2727
             byte[] databox = getRawContentDataOnly();
 149  
 
 150  
             //Wrap in Parent box
 151  2727
             ByteArrayOutputStream outerbaos = new ByteArrayOutputStream();
 152  2727
             outerbaos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + databox.length));
 153  2727
             outerbaos.write(Utils.getDefaultBytes(getId(), "ISO-8859-1"));
 154  2727
             outerbaos.write(databox);
 155  2727
             return outerbaos.toByteArray();
 156  
         }
 157  0
         catch (IOException ioe)
 158  
         {
 159  
             //This should never happen as were not actually writing to/from a file
 160  0
             throw new RuntimeException(ioe);
 161  
         }
 162  
     }
 163  
 
 164  
     /**
 165  
      * Get raw content for the data component only
 166  
      *
 167  
      * @return
 168  
      * @throws UnsupportedEncodingException
 169  
      */
 170  
     public byte[] getRawContentDataOnly() throws UnsupportedEncodingException
 171  
     {
 172  2851
         logger.fine("Getting Raw data for:" + getId());
 173  
         try
 174  
         {
 175  
             //Create Data Box
 176  2851
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 177  2851
             byte[] data = getDataBytes();
 178  2851
             baos.write(Utils.getSizeBEInt32(Mp4DataBox.DATA_HEADER_LENGTH + data.length));
 179  2851
             baos.write(Utils.getDefaultBytes(Mp4DataBox.IDENTIFIER, "ISO-8859-1"));
 180  2851
             baos.write(new byte[]{0});
 181  2851
             baos.write(new byte[]{0, 0, (byte) getFieldType().getFileClassId()});
 182  2851
             baos.write(new byte[]{0, 0, 0, 0});
 183  2851
             baos.write(data);
 184  2851
             return baos.toByteArray();
 185  
         }
 186  0
         catch (IOException ioe)
 187  
         {
 188  
             //This should never happen as were not actually writing to/from a file
 189  0
             throw new RuntimeException(ioe);
 190  
         }
 191  
     }
 192  
 }