Coverage Report - org.jaudiotagger.audio.asf.data.ChunkContainer
 
Classes in this File Line Coverage Branch Coverage Complexity
ChunkContainer
52%
23/44
36%
8/22
0
 
 1  
 package org.jaudiotagger.audio.asf.data;
 2  
 
 3  
 import org.jaudiotagger.audio.asf.util.ChunkPositionComparator;
 4  
 import org.jaudiotagger.audio.asf.util.Utils;
 5  
 
 6  
 import java.math.BigInteger;
 7  
 import java.util.*;
 8  
 
 9  
 /**
 10  
  * Stores multiple ASF objects (chunks) in form of {@link Chunk} objects, and is itself an ASF object (chunk).<br>  
 11  
  * 
 12  
  * @author Christian Laireiter
 13  
  */
 14  7
 public class ChunkContainer extends Chunk
 15  
 {
 16  
 
 17  
     /**
 18  
      * Stores the {@link GUID} instances, which are allowed multiple times
 19  
      * within an ASF header.
 20  
      */
 21  
     private final static HashSet<GUID> MULTI_CHUNKS;
 22  
 
 23  
     static
 24  
     {
 25  7
         MULTI_CHUNKS = new HashSet<GUID>();
 26  7
         MULTI_CHUNKS.add(GUID.GUID_STREAM);
 27  7
     }
 28  
 
 29  
     /**
 30  
      * Stores the {@link Chunk} objects to their {@link GUID}.
 31  
      */
 32  
     private final Map<GUID, List<Chunk>> chunkTable;
 33  
 
 34  
     /**
 35  
      * Creates an instance.
 36  
      * @param chunkGUID the GUID which identifies the chunk.
 37  
      * @param pos the position of the chunk within the stream.
 38  
      * @param length the length of the chunk.
 39  
      */
 40  
     public ChunkContainer(final GUID chunkGUID, final long pos, final BigInteger length)
 41  
     {
 42  160
         super(chunkGUID, pos, length);
 43  160
         this.chunkTable = new Hashtable<GUID, List<Chunk>>();
 44  160
     }
 45  
 
 46  
     /**
 47  
      * Adds a chunk to the container.<br>
 48  
      * @param toAdd The chunk which is to be added.
 49  
      */
 50  
     public void addChunk(final Chunk toAdd)
 51  
     {
 52  325
         List<Chunk> list = assertChunkList(toAdd.getGuid());
 53  325
         if (!list.isEmpty() && !MULTI_CHUNKS.contains(toAdd.getGuid()))
 54  
         {
 55  0
             throw new IllegalArgumentException("The GUID of the given chunk indicates, that there is no more instance allowed."); //$NON-NLS-1$
 56  
         }
 57  325
         list.add(toAdd);
 58  325
         assert chunkstartsUnique() : "Chunk has equal start position like an already inserted one."; //$NON-NLS-1$
 59  325
     }
 60  
 
 61  
     /**
 62  
      * This method asserts that a {@link List} exists for the given {@link GUID}, 
 63  
      * in {@link #chunkTable}.<br>
 64  
      * @param lookFor The GUID to get list for.
 65  
      * @return an already existing, or newly created list.
 66  
      */
 67  
     protected List<Chunk> assertChunkList(final GUID lookFor)
 68  
     {
 69  559
         List<Chunk> result = this.chunkTable.get(lookFor);
 70  559
         if (result == null)
 71  
         {
 72  325
             result = new ArrayList<Chunk>();
 73  325
             this.chunkTable.put(lookFor, result);
 74  
         }
 75  559
         return result;
 76  
     }
 77  
 
 78  
     /**
 79  
      * Tests whether all stored chunks have a unique starting position among
 80  
      * their brothers.
 81  
      * @return <code>true</code> if all chunks are located at an unique position. However, no intersection is tested.
 82  
      */
 83  
     private boolean chunkstartsUnique()
 84  
     {
 85  0
         boolean result = true;
 86  0
         HashSet<Long> chunkStarts = new HashSet<Long>();
 87  0
         Collection<Chunk> chunks = getChunks();
 88  0
         for (Chunk curr : chunks)
 89  
         {
 90  0
             result &= chunkStarts.add(curr.getPosition());
 91  
         }
 92  0
         return result;
 93  
     }
 94  
 
 95  
     /**
 96  
      * Returns a collection of all contained chunks.<br>
 97  
      * 
 98  
      * @return all contained chunks
 99  
      */
 100  
     public Collection<Chunk> getChunks()
 101  
     {
 102  0
         final List<Chunk> result = new ArrayList<Chunk>();
 103  0
         for (List<Chunk> curr : this.chunkTable.values())
 104  
         {
 105  0
             result.addAll(curr);
 106  
         }
 107  0
         return result;
 108  
     }
 109  
 
 110  
     /**
 111  
      * Looks for the first stored chunk which has the given GUID.
 112  
      * 
 113  
      * @param lookFor GUID to look up.
 114  
      * @param instanceOf The class which must additionally be matched. 
 115  
      * @return <code>null</code> if no chunk was found, or the stored instance doesn't match.
 116  
      */
 117  
     protected Chunk getFirst(GUID lookFor, Class<? extends Chunk> instanceOf)
 118  
     {
 119  758
         List<Chunk> list = this.chunkTable.get(lookFor);
 120  758
         if (list != null && !list.isEmpty())
 121  
         {
 122  565
             Chunk result = list.get(0);
 123  565
             if (result.getClass().isAssignableFrom(instanceOf))
 124  
             {
 125  565
                 return result;
 126  
             }
 127  
         }
 128  193
         return null;
 129  
     }
 130  
 
 131  
     /**
 132  
      * {@inheritDoc}
 133  
      */
 134  
     @Override
 135  
     public String prettyPrint(String prefix)
 136  
     {
 137  0
         return prettyPrint(prefix, "");
 138  
     }
 139  
 
 140  
     /**
 141  
      * Nearly the same as {@link #prettyPrint(String)} however, additional information can be injected
 142  
      * below the {@link Chunk#prettyPrint(String)} output and the listing of the contained chunks.<br>
 143  
      * 
 144  
      * @param prefix The prefix to prepend.
 145  
      * @param containerInfo Information to inject.
 146  
      * @return Information of current Chunk Object.
 147  
      */
 148  
     public String prettyPrint(final String prefix, final String containerInfo)
 149  
     {
 150  0
         final StringBuffer result = new StringBuffer(super.prettyPrint(prefix));
 151  0
         result.append(containerInfo);
 152  0
         result.append(prefix + "  |" + Utils.LINE_SEPARATOR);
 153  0
         final ArrayList<Chunk> list = new ArrayList<Chunk>(getChunks());
 154  0
         Collections.sort(list, new ChunkPositionComparator());
 155  
 
 156  0
         for (Chunk curr : list)
 157  
         {
 158  0
             result.append(curr.prettyPrint(prefix + "  |"));
 159  0
             result.append(prefix + "  |" + Utils.LINE_SEPARATOR);
 160  
         }
 161  0
         return result.toString();
 162  
     }
 163  
 }