Coverage Report - org.jaudiotagger.tag.mp4.field.Mp4TagReverseDnsField
 
Classes in this File Line Coverage Branch Coverage Complexity
Mp4TagReverseDnsField
78%
65/83
66%
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 parentHeader
 53  
      * @param data
 54  
      * @throws UnsupportedEncodingException
 55  
      */
 56  
     public Mp4TagReverseDnsField(Mp4BoxHeader parentHeader, ByteBuffer data) throws UnsupportedEncodingException
 57  
     {
 58  1790
         super(parentHeader, data);
 59  1790
     }
 60  
 
 61  
     /**
 62  
      * Newly created Reverse Dns field
 63  
      *
 64  
      * @param id
 65  
      * @param content
 66  
      */
 67  
     public Mp4TagReverseDnsField(Mp4FieldKey id, String content)
 68  
     {
 69  294
         super(id.getFieldName());
 70  294
         this.issuer = id.getIssuer();
 71  294
         this.descriptor = id.getIdentifier();
 72  294
         this.content = content;
 73  294
     }
 74  
 
 75  
     /**
 76  
      * Newly created Reverse Dns field bypassing the Mp4TagField enum for creation of temporary reverse dns fields
 77  
      * @param fieldName
 78  
      * @param issuer
 79  
      * @param identifier
 80  
      * @param content
 81  
      */
 82  
     public Mp4TagReverseDnsField(final String fieldName, final String issuer, final String identifier, final String content)
 83  
     {
 84  0
         super(fieldName);
 85  0
         this.issuer     = issuer;
 86  0
         this.descriptor = identifier;
 87  0
         this.content    = content;
 88  0
     }
 89  
 
 90  
     public Mp4FieldType getFieldType()
 91  
     {
 92  
         //TODO always assuming text at moment but may not always be the case (though dont have any concrete
 93  
         //examples)
 94  866
         return Mp4FieldType.TEXT;
 95  
     }
 96  
 
 97  
     protected void build(ByteBuffer data) throws UnsupportedEncodingException
 98  
     {
 99  
         //Read mean box, set the issuer and skip over data
 100  1790
         Mp4BoxHeader meanBoxHeader = new Mp4BoxHeader(data);
 101  1790
         Mp4MeanBox meanBox = new Mp4MeanBox(meanBoxHeader, data);
 102  1790
         setIssuer(meanBox.getIssuer());
 103  1790
         data.position(data.position() + meanBoxHeader.getDataLength());
 104  
 
 105  
         //Read name box, identify what type of field it is
 106  1790
         Mp4BoxHeader nameBoxHeader = new Mp4BoxHeader(data);
 107  1790
         Mp4NameBox nameBox = new Mp4NameBox(nameBoxHeader, data);
 108  1790
         setDescriptor(nameBox.getName());
 109  1790
         data.position(data.position() + nameBoxHeader.getDataLength());
 110  
 
 111  
         //Issue 198:There is not actually a data atom there cannot cant be because no room for one
 112  1790
         if (parentHeader.getDataLength() == meanBoxHeader.getLength() + nameBoxHeader.getLength())
 113  
         {
 114  5
             id = IDENTIFIER + ":" + issuer + ":" + descriptor;
 115  5
             setContent("");
 116  5
             logger.warning(ErrorMessage.MP4_REVERSE_DNS_FIELD_HAS_NO_DATA.getMsg(id));
 117  
         }
 118  
         //Usual Case
 119  
         else
 120  
         {
 121  
             //Read data box, identify the data
 122  1785
             Mp4BoxHeader dataBoxHeader = new Mp4BoxHeader(data);
 123  1785
             Mp4DataBox dataBox = new Mp4DataBox(dataBoxHeader, data);
 124  1785
             setContent(dataBox.getContent());
 125  1785
             data.position(data.position() + dataBoxHeader.getDataLength());
 126  
 
 127  
             //Now calculate the id which in order to be unique needs to use all htree values
 128  1785
             id = IDENTIFIER + ":" + issuer + ":" + descriptor;
 129  
         }
 130  1790
     }
 131  
 
 132  
 
 133  
     public void copyContent(TagField field)
 134  
     {
 135  0
         if (field instanceof Mp4TagReverseDnsField)
 136  
         {
 137  0
             this.issuer = ((Mp4TagReverseDnsField) field).getIssuer();
 138  0
             this.descriptor = ((Mp4TagReverseDnsField) field).getDescriptor();
 139  0
             this.content = ((Mp4TagReverseDnsField) field).getContent();
 140  
         }
 141  0
     }
 142  
 
 143  
     /**
 144  
      * @return content
 145  
      */
 146  
     public String getContent()
 147  
     {
 148  60
         return content;
 149  
     }
 150  
 
 151  
 
 152  
     protected byte[] getDataBytes() throws UnsupportedEncodingException
 153  
     {
 154  0
         return content.getBytes(getEncoding());
 155  
     }
 156  
 
 157  
     public String getEncoding()
 158  
     {
 159  2600
         return Mp4BoxHeader.CHARSET_UTF_8;
 160  
     }
 161  
 
 162  
     /**
 163  
      * Convert back to raw content, includes ----,mean,name and data atom as views as one thing externally
 164  
      *
 165  
      * @return
 166  
      * @throws UnsupportedEncodingException
 167  
      */
 168  
     public byte[] getRawContent() throws UnsupportedEncodingException
 169  
     {
 170  
         try
 171  
         {
 172  867
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 173  
 
 174  
             //Create Meanbox data
 175  867
             byte[] issuerRawData = issuer.getBytes(getEncoding());
 176  867
             baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + Mp4MeanBox.PRE_DATA_LENGTH + issuerRawData.length));
 177  867
             baos.write(Utils.getDefaultBytes(Mp4MeanBox.IDENTIFIER, "ISO-8859-1"));
 178  867
             baos.write(new byte[]{0, 0, 0, 0});
 179  867
             baos.write(issuerRawData);
 180  
 
 181  
             //Create Namebox data
 182  867
             byte[] nameRawData = descriptor.getBytes(getEncoding());
 183  867
             baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + Mp4NameBox.PRE_DATA_LENGTH + nameRawData.length));
 184  867
             baos.write(Utils.getDefaultBytes(Mp4NameBox.IDENTIFIER, "ISO-8859-1"));
 185  867
             baos.write(new byte[]{0, 0, 0, 0});
 186  867
             baos.write(nameRawData);
 187  
 
 188  
             //Create DataBox data if we have data only
 189  867
             if (content.length() > 0)
 190  
             {
 191  866
                 baos.write(getRawContentDataOnly());
 192  
             }
 193  
             //Now wrap with reversedns box
 194  867
             ByteArrayOutputStream outerbaos = new ByteArrayOutputStream();
 195  867
             outerbaos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + baos.size()));
 196  867
             outerbaos.write(Utils.getDefaultBytes(IDENTIFIER, "ISO-8859-1"));
 197  867
             outerbaos.write(baos.toByteArray());
 198  867
             return outerbaos.toByteArray();
 199  
 
 200  
         }
 201  0
         catch (IOException ioe)
 202  
         {
 203  
             //This should never happen as were not actually writing to/from a file
 204  0
             throw new RuntimeException(ioe);
 205  
         }
 206  
     }
 207  
 
 208  
     public byte[] getRawContentDataOnly() throws UnsupportedEncodingException
 209  
     {
 210  866
         logger.fine("Getting Raw data for:" + getId());
 211  
         try
 212  
         {
 213  
             //Create DataBox data
 214  866
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
 215  866
             byte[] dataRawData = content.getBytes(getEncoding());
 216  866
             baos.write(Utils.getSizeBEInt32(Mp4BoxHeader.HEADER_LENGTH + Mp4DataBox.PRE_DATA_LENGTH + dataRawData.length));
 217  866
             baos.write(Utils.getDefaultBytes(Mp4DataBox.IDENTIFIER, "ISO-8859-1"));
 218  866
             baos.write(new byte[]{0});
 219  866
             baos.write(new byte[]{0, 0, (byte) getFieldType().getFileClassId()});
 220  866
             baos.write(new byte[]{0, 0, 0, 0});
 221  866
             baos.write(dataRawData);
 222  866
             return baos.toByteArray();
 223  
         }
 224  0
         catch (IOException ioe)
 225  
         {
 226  
             //This should never happen as were not actually writing to/from a file
 227  0
             throw new RuntimeException(ioe);
 228  
         }
 229  
     }
 230  
 
 231  
     public boolean isBinary()
 232  
     {
 233  0
         return false;
 234  
     }
 235  
 
 236  
     public boolean isEmpty()
 237  
     {
 238  0
         return this.content.trim().equals("");
 239  
     }
 240  
 
 241  
     public void setContent(String s)
 242  
     {
 243  1790
         this.content = s;
 244  1790
     }
 245  
 
 246  
     public void setEncoding(String s)
 247  
     {
 248  
         /* Not allowed */
 249  0
     }
 250  
 
 251  
     public String toString()
 252  
     {
 253  1820
         return content;
 254  
     }
 255  
 
 256  
     /**
 257  
      * @return the issuer
 258  
      */
 259  
     public String getIssuer()
 260  
     {
 261  60
         return issuer;
 262  
     }
 263  
 
 264  
     /**
 265  
      * @return the descriptor
 266  
      */
 267  
     public String getDescriptor()
 268  
     {
 269  60
         return descriptor;
 270  
     }
 271  
 
 272  
     /**
 273  
      * Set the issuer, usually reverse dns of the Companies domain
 274  
      *
 275  
      * @param issuer
 276  
      */
 277  
     public void setIssuer(String issuer)
 278  
     {
 279  1790
         this.issuer = issuer;
 280  1790
     }
 281  
 
 282  
     /**
 283  
      * Set the descriptor for the data (what type of data it is)
 284  
      *
 285  
      * @param descriptor
 286  
      */
 287  
     public void setDescriptor(String descriptor)
 288  
     {
 289  1790
         this.descriptor = descriptor;
 290  1790
     }
 291  
 }