Coverage Report - org.jaudiotagger.tag.mp4.field.Mp4TagReverseDnsField
 
Classes in this File Line Coverage Branch Coverage Complexity
Mp4TagReverseDnsField
78%
65/83
67%
4/6
1.45
 
 1  
 package org.jaudiotagger.tag.mp4.field;
 2  
 
 3  
 import org.jaudiotagger.audio.generic.Utils;
 4  
 import org.jaudiotagger.audio.mp4.atom.Mp4BoxHeader;
 5  
 import org.jaudiotagger.logging.ErrorMessage;
 6  
 import org.jaudiotagger.tag.TagField;
 7  
 import org.jaudiotagger.tag.TagTextField;
 8  
 import org.jaudiotagger.tag.mp4.Mp4FieldKey;
 9  
 import org.jaudiotagger.tag.mp4.Mp4TagField;
 10  
 import org.jaudiotagger.tag.mp4.atom.Mp4DataBox;
 11  
 import org.jaudiotagger.tag.mp4.atom.Mp4MeanBox;
 12  
 import org.jaudiotagger.tag.mp4.atom.Mp4NameBox;
 13  
 
 14  
 import java.io.ByteArrayOutputStream;
 15  
 import java.io.IOException;
 16  
 import java.io.UnsupportedEncodingException;
 17  
 import java.nio.ByteBuffer;
 18  
 
 19  
 /**
 20  
  * Represents reverse dns field, used for custom information
 21  
  * <p/>
 22  
  * <p>Originally only used by Itunes for information that was iTunes specific but now used in a wide range of uses,
 23  
  * for example Musicbrainz uses it for many of its fields.
 24  
  * <p/>
 25  
  * These fields have a more complex setup
 26  
  * Box ----  shows this is a reverse dns metadata field
 27  
  * Box mean  the issuer in the form of reverse DNS domain (e.g com.apple.iTunes)
 28  
  * Box name  descriptor identifying the type of contents
 29  
  * Box data  contents
 30  
  * <p/>
 31  
  * The raw data passed starts from the mean box
 32  
  */
 33  
 public class Mp4TagReverseDnsField extends Mp4TagField implements TagTextField
 34  
 {
 35  
     public static final String IDENTIFIER = "----";
 36  
 
 37  
     protected int dataSize;
 38  
 
 39  
     //Issuer
 40  
     private String issuer;
 41  
 
 42  
     //Descriptor
 43  
     private String descriptor;
 44  
 
 45  
     //Data Content,
 46  
     //TODO assuming always text at the moment
 47  
     protected String content;
 48  
 
 49  
     /**
 50  
      * Construct from existing file data
 51  
      *
 52  
      * @param data
 53  
      * @throws UnsupportedEncodingException
 54  
      */
 55  
     public Mp4TagReverseDnsField(Mp4BoxHeader parentHeader, ByteBuffer data) throws UnsupportedEncodingException
 56  
     {
 57  450
         super(parentHeader, data);
 58  450
     }
 59  
 
 60  
     /**
 61  
      * Newly created Reverse Dns field
 62  
      *
 63  
      * @param id
 64  
      * @param content
 65  
      */
 66  
     public Mp4TagReverseDnsField(Mp4FieldKey id, String content)
 67  
     {
 68  66
         super(id.getFieldName());
 69  66
         this.issuer = id.getIssuer();
 70  66
         this.descriptor = id.getIdentifier();
 71  66
         this.content = content;
 72  66
     }
 73  
 
 74  
     /**
 75  
      * Newly created Reverse Dns field bypassing the Mp4TagField enum for creation of temporary reverse dns fields
 76  
      */
 77  
     public Mp4TagReverseDnsField(final String fieldName, final String issuer, final String identifier, final String content)
 78  
     {
 79  0
         super(fieldName);
 80  0
         this.issuer     = issuer;
 81  0
         this.descriptor = identifier;
 82  0
         this.content    = content;
 83  0
     }
 84  
 
 85  
     public Mp4FieldType getFieldType()
 86  
     {
 87  
         //TODO always assuming text at moment but may not always be the case (though dont have any concrete
 88  
         //examples)
 89  214
         return Mp4FieldType.TEXT;
 90  
     }
 91  
 
 92  
     protected void build(ByteBuffer data) throws UnsupportedEncodingException
 93  
     {
 94  
         //Read mean box, set the issuer and skip over data
 95  450
         Mp4BoxHeader meanBoxHeader = new Mp4BoxHeader(data);
 96  450
         Mp4MeanBox meanBox = new Mp4MeanBox(meanBoxHeader, data);
 97  450
         setIssuer(meanBox.getIssuer());
 98  450
         data.position(data.position() + meanBoxHeader.getDataLength());
 99  
 
 100  
         //Read name box, identify what type of field it is
 101  450
         Mp4BoxHeader nameBoxHeader = new Mp4BoxHeader(data);
 102  450
         Mp4NameBox nameBox = new Mp4NameBox(nameBoxHeader, data);
 103  450
         setDescriptor(nameBox.getName());
 104  450
         data.position(data.position() + nameBoxHeader.getDataLength());
 105  
 
 106  
         //Issue 198:There is not actually a data atom there cannot cant be because no room for one
 107  450
         if (parentHeader.getDataLength() == meanBoxHeader.getLength() + nameBoxHeader.getLength())
 108  
         {
 109  5
             id = IDENTIFIER + ":" + issuer + ":" + descriptor;
 110  5
             setContent("");
 111  5
             logger.warning(ErrorMessage.MP4_REVERSE_DNS_FIELD_HAS_NO_DATA.getMsg(id));
 112  
         }
 113  
         //Usual Case
 114  
         else
 115  
         {
 116  
             //Read data box, identify the data
 117  445
             Mp4BoxHeader dataBoxHeader = new Mp4BoxHeader(data);
 118  445
             Mp4DataBox dataBox = new Mp4DataBox(dataBoxHeader, data);
 119  445
             setContent(dataBox.getContent());
 120  445
             data.position(data.position() + dataBoxHeader.getDataLength());
 121  
 
 122  
             //Now calculate the id which in order to be unique needs to use all htree values
 123  445
             id = IDENTIFIER + ":" + issuer + ":" + descriptor;
 124  
         }
 125  450
     }
 126  
 
 127  
 
 128  
     public void copyContent(TagField field)
 129  
     {
 130  0
         if (field instanceof Mp4TagReverseDnsField)
 131  
         {
 132  0
             this.issuer = ((Mp4TagReverseDnsField) field).getIssuer();
 133  0
             this.descriptor = ((Mp4TagReverseDnsField) field).getDescriptor();
 134  0
             this.content = ((Mp4TagReverseDnsField) field).getContent();
 135  
         }
 136  0
     }
 137  
 
 138  
     /**
 139  
      * @return content
 140  
      */
 141  
     public String getContent()
 142  
     {
 143  15
         return content;
 144  
     }
 145  
 
 146  
 
 147  
     protected byte[] getDataBytes() throws UnsupportedEncodingException
 148  
     {
 149  0
         return content.getBytes(getEncoding());
 150  
     }
 151  
 
 152  
     public String getEncoding()
 153  
     {
 154  644
         return Mp4BoxHeader.CHARSET_UTF_8;
 155  
     }
 156  
 
 157  
     /**
 158  
      * Convert back to raw content, includes ----,mean,name and data atom as views as one thing externally
 159  
      *
 160  
      * @return
 161  
      * @throws UnsupportedEncodingException
 162  
      */
 163  
     public byte[] getRawContent() throws UnsupportedEncodingException
 164  
     {
 165  
         try
 166  
         {
 167  215
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 168  
 
 169  
             //Create Meanbox data
 170  215
             byte[] issuerRawData = issuer.getBytes(getEncoding());
 171  215
             baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + Mp4MeanBox.PRE_DATA_LENGTH + issuerRawData.length));
 172  215
             baos.write(Utils.getDefaultBytes(Mp4MeanBox.IDENTIFIER, "ISO-8859-1"));
 173  215
             baos.write(new byte[]{0, 0, 0, 0});
 174  215
             baos.write(issuerRawData);
 175  
 
 176  
             //Create Namebox data
 177  215
             byte[] nameRawData = descriptor.getBytes(getEncoding());
 178  215
             baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + Mp4NameBox.PRE_DATA_LENGTH + nameRawData.length));
 179  215
             baos.write(Utils.getDefaultBytes(Mp4NameBox.IDENTIFIER, "ISO-8859-1"));
 180  215
             baos.write(new byte[]{0, 0, 0, 0});
 181  215
             baos.write(nameRawData);
 182  
 
 183  
             //Create DataBox data if we have data only
 184  215
             if (content.length() > 0)
 185  
             {
 186  214
                 baos.write(getRawContentDataOnly());
 187  
             }
 188  
             //Now wrap with reversedns box
 189  215
             ByteArrayOutputStream outerbaos = new ByteArrayOutputStream();
 190  215
             outerbaos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + baos.size()));
 191  215
             outerbaos.write(Utils.getDefaultBytes(IDENTIFIER, "ISO-8859-1"));
 192  215
             outerbaos.write(baos.toByteArray());
 193  215
             return outerbaos.toByteArray();
 194  
 
 195  
         }
 196  0
         catch (IOException ioe)
 197  
         {
 198  
             //This should never happen as were not actually writing to/from a file
 199  0
             throw new RuntimeException(ioe);
 200  
         }
 201  
     }
 202  
 
 203  
     public byte[] getRawContentDataOnly() throws UnsupportedEncodingException
 204  
     {
 205  214
         logger.fine("Getting Raw data for:" + getId());
 206  
         try
 207  
         {
 208  
             //Create DataBox data
 209  214
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 210  214
             byte[] dataRawData = content.getBytes(getEncoding());
 211  214
             baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + Mp4DataBox.PRE_DATA_LENGTH + dataRawData.length));
 212  214
             baos.write(Utils.getDefaultBytes(Mp4DataBox.IDENTIFIER, "ISO-8859-1"));
 213  214
             baos.write(new byte[]{0});
 214  214
             baos.write(new byte[]{0, 0, (byte) getFieldType().getFileClassId()});
 215  214
             baos.write(new byte[]{0, 0, 0, 0});
 216  214
             baos.write(dataRawData);
 217  214
             return baos.toByteArray();
 218  
         }
 219  0
         catch (IOException ioe)
 220  
         {
 221  
             //This should never happen as were not actually writing to/from a file
 222  0
             throw new RuntimeException(ioe);
 223  
         }
 224  
     }
 225  
 
 226  
     public boolean isBinary()
 227  
     {
 228  0
         return false;
 229  
     }
 230  
 
 231  
     public boolean isEmpty()
 232  
     {
 233  0
         return this.content.trim().equals("");
 234  
     }
 235  
 
 236  
     public void setContent(String s)
 237  
     {
 238  450
         this.content = s;
 239  450
     }
 240  
 
 241  
     public void setEncoding(String s)
 242  
     {
 243  
         /* Not allowed */
 244  0
     }
 245  
 
 246  
     public String toString()
 247  
     {
 248  460
         return content;
 249  
     }
 250  
 
 251  
     /**
 252  
      * @return the issuer
 253  
      */
 254  
     public String getIssuer()
 255  
     {
 256  15
         return issuer;
 257  
     }
 258  
 
 259  
     /**
 260  
      * @return the descriptor
 261  
      */
 262  
     public String getDescriptor()
 263  
     {
 264  15
         return descriptor;
 265  
     }
 266  
 
 267  
     /**
 268  
      * Set the issuer, usually reverse dns of the Companies domain
 269  
      *
 270  
      * @param issuer
 271  
      */
 272  
     public void setIssuer(String issuer)
 273  
     {
 274  450
         this.issuer = issuer;
 275  450
     }
 276  
 
 277  
     /**
 278  
      * Set the descriptor for the data (what type of data it is)
 279  
      *
 280  
      * @param descriptor
 281  
      */
 282  
     public void setDescriptor(String descriptor)
 283  
     {
 284  450
         this.descriptor = descriptor;
 285  450
     }
 286  
 }