Coverage Report - org.jaudiotagger.audio.asf.AsfFileWriter
 
Classes in this File Line Coverage Branch Coverage Complexity
AsfFileWriter
100%
30/30
79%
19/24
3.667
 
 1  
 /*
 2  
  * Entagged Audio Tag library
 3  
  * Copyright (c) 2004-2005 Christian Laireiter <liree@web.de>
 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.audio.asf;
 20  
 
 21  
 import org.jaudiotagger.audio.asf.data.AsfHeader;
 22  
 import org.jaudiotagger.audio.asf.data.ChunkContainer;
 23  
 import org.jaudiotagger.audio.asf.data.MetadataContainer;
 24  
 import org.jaudiotagger.audio.asf.io.*;
 25  
 import org.jaudiotagger.tag.asf.AsfTag;
 26  
 import org.jaudiotagger.audio.asf.util.TagConverter;
 27  
 import org.jaudiotagger.audio.exceptions.CannotWriteException;
 28  
 import org.jaudiotagger.audio.generic.AudioFileWriter;
 29  
 import org.jaudiotagger.tag.Tag;
 30  
 
 31  
 import java.io.IOException;
 32  
 import java.io.RandomAccessFile;
 33  
 import java.util.ArrayList;
 34  
 import java.util.List;
 35  
 
 36  
 /**
 37  
  * This class writes given tags to ASF files containing WMA content. <br>
 38  
  * <br>
 39  
  * 
 40  
  * @author Christian Laireiter
 41  
  */
 42  8
 public class AsfFileWriter extends AudioFileWriter {
 43  
 
 44  
     /**
 45  
      * {@inheritDoc}
 46  
      */
 47  
     @Override
 48  
     protected void deleteTag(final RandomAccessFile raf,
 49  
             final RandomAccessFile tempRaf) throws CannotWriteException,
 50  
             IOException {
 51  52
         writeTag(new AsfTag(true), raf, tempRaf);
 52  52
     }
 53  
 
 54  
     private boolean[] searchExistence(final ChunkContainer container,
 55  
             final MetadataContainer[] metaContainers) {
 56  266
         assert container != null;
 57  266
         assert metaContainers != null;
 58  266
         final boolean[] result = new boolean[metaContainers.length];
 59  1596
         for (int i = 0; i < result.length; i++) {
 60  1330
             result[i] = container.hasChunkByGUID(metaContainers[i]
 61  
                     .getContainerType().getContainerGUID());
 62  
         }
 63  266
         return result;
 64  
     }
 65  
 
 66  
     /**
 67  
      * {@inheritDoc}
 68  
      */
 69  
     @Override
 70  
     protected void writeTag(final Tag tag, final RandomAccessFile raf,
 71  
             final RandomAccessFile rafTemp) throws CannotWriteException,
 72  
             IOException {
 73  
         /*
 74  
          * Since this implementation should not change the structure of the ASF
 75  
          * file (locations of content description chunks), we need to read the
 76  
          * content description chunk and the extended content description chunk
 77  
          * from the source file. In the second step we need to determine which
 78  
          * modifier (asf header or asf extended header) gets the appropriate
 79  
          * modifiers. The following policies are applied: if the source does not
 80  
          * contain any descriptor, the necessary descriptors are appended to the
 81  
          * header object.
 82  
          * 
 83  
          * if the source contains only one descriptor in the header extension
 84  
          * object, and the other type is needed as well, the other one will be
 85  
          * put into the header extension object.
 86  
          * 
 87  
          * for each descriptor type, if an object is found, an updater will be
 88  
          * configured.
 89  
          */
 90  133
         final AsfHeader sourceHeader = AsfHeaderReader.readTagHeader(raf);
 91  133
         raf.seek(0); // Reset for the streamer
 92  
         /*
 93  
          * Now createField modifiers for metadata descriptor and extended content
 94  
          * descriptor as implied by the given Tag.
 95  
          */
 96  
         // TODO not convinced that we need to copy fields here
 97  133
         final AsfTag copy = new AsfTag(tag, true);
 98  133
         final MetadataContainer[] distribution = TagConverter
 99  
                 .distributeMetadata(copy);
 100  133
         final boolean[] existHeader = searchExistence(sourceHeader,
 101  
                 distribution);
 102  133
         final boolean[] existExtHeader = searchExistence(sourceHeader
 103  
                 .getExtendedHeader(), distribution);
 104  
         // Modifiers for the asf header object
 105  133
         final List<ChunkModifier> headerModifier = new ArrayList<ChunkModifier>();
 106  
         // Modifiers for the asf header extension object
 107  133
         final List<ChunkModifier> extHeaderModifier = new ArrayList<ChunkModifier>();
 108  798
         for (int i = 0; i < distribution.length; i++) {
 109  665
             final WriteableChunkModifer modifier = new WriteableChunkModifer(
 110  
                     distribution[i]);
 111  665
             if (existHeader[i]) {
 112  
                 // Will remove or modify chunks in ASF header
 113  158
                 headerModifier.add(modifier);
 114  507
             } else if (existExtHeader[i]) {
 115  
                 // Will remove or modify chunks in extended header
 116  66
                 extHeaderModifier.add(modifier);
 117  
             } else {
 118  
                 // Objects (chunks) will be added here.
 119  441
                 if (i == 0 || i == 2 || i == 1) {
 120  
                     // Add content description and extended content description
 121  
                     // at header for maximum compatibility
 122  241
                     headerModifier.add(modifier);
 123  
                 } else {
 124  
                     // For now, the rest should be created at extended header
 125  
                     // since other positions aren't known.
 126  200
                     extHeaderModifier.add(modifier);
 127  
                 }
 128  
             }
 129  
         }
 130  
         // only addField an AsfExtHeaderModifier, if there is actually something to
 131  
         // change (performance)
 132  133
         if (!extHeaderModifier.isEmpty()) {
 133  133
             headerModifier.add(new AsfExtHeaderModifier(extHeaderModifier));
 134  
         }
 135  133
         new AsfStreamer()
 136  
                 .createModifiedCopy(new RandomAccessFileInputstream(raf),
 137  
                         new RandomAccessFileOutputStream(rafTemp),
 138  
                         headerModifier);
 139  133
     }
 140  
 
 141  
 }