EMMA Coverage Report (generated Tue Mar 14 21:50:42 EST 2006)
[all classes][org.farng.mp3.id3]

COVERAGE SUMMARY FOR SOURCE FILE [ID3v2_3Frame.java]

nameclass, %method, %block, %line, %
ID3v2_3Frame.java100% (1/1)73%  (8/11)58%  (350/605)52%  (61.4/118)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ID3v2_3Frame100% (1/1)73%  (8/11)58%  (350/605)52%  (61.4/118)
ID3v2_3Frame (AbstractID3v2Frame): void 0%   (0/1)0%   (0/68)0%   (0/20)
ID3v2_3Frame (boolean, boolean, boolean, boolean, AbstractID3v2FrameBody): void 0%   (0/1)0%   (0/36)0%   (0/13)
write (RandomAccessFile): void 0%   (0/1)0%   (0/125)0%   (0/26)
equals (Object): boolean 100% (1/1)74%  (40/54)56%  (9/16)
read (RandomAccessFile): void 100% (1/1)91%  (126/138)97%  (23.4/24)
ID3v2_3Frame (): void 100% (1/1)100% (23/23)100% (9/9)
ID3v2_3Frame (AbstractID3v2FrameBody): void 100% (1/1)100% (24/24)100% (9/9)
ID3v2_3Frame (ID3v2_3Frame): void 100% (1/1)100% (46/46)100% (14/14)
ID3v2_3Frame (RandomAccessFile): void 100% (1/1)100% (24/24)100% (9/9)
getSize (): int 100% (1/1)100% (10/10)100% (1/1)
setAlterPreservation (): void 100% (1/1)100% (57/57)100% (7/7)

1package org.farng.mp3.id3;
2 
3import org.farng.mp3.InvalidTagException;
4import org.farng.mp3.TagConstant;
5import org.farng.mp3.TagUtility;
6 
7import java.io.IOException;
8import java.io.RandomAccessFile;
9 
10/**
11 * <p class=t> The extended header contains information that is not vital to the correct parsing of the tag information,
12 * hence the extended header is optional. </p>
13 * <p/>
14 * <p><center> <table border=0> <tr><td nowrap> Extended header size</td><td rowspan=3>&nbsp;</td><td width=100%>$xx xx
15 * xx xx</td></tr> <tr><td>Extended Flags</td><td>$xx xx</td></tr> <tr><td>Size of padding</td><td>$xx xx xx xx</tr>
16 * </table> </center>
17 * <p/>
18 * <p class=t> Where the 'Extended header size', currently 6 or 10 bytes, excludes itself. The 'Size of padding' is
19 * simply the total tag size excluding the frames and the headers, in other words the padding. The extended header is
20 * considered separate from the header proper, and as such is subject to unsynchronisation. </p>
21 * <p/>
22 * <p class=t> The extended flags are a secondary flag set which describes further attributes of the tag. These
23 * attributes are currently defined as follows </p>
24 * <p/>
25 * <p class=ind> %x0000000 00000000 </p>
26 * <p/>
27 * <p class=t> x - CRC data present </p>
28 * <p/>
29 * <p class=ind> If this flag is set four bytes of CRC-32 data is appended to the extended header. The CRC should be
30 * calculated before unsynchronisation on the data between the extended header and the padding, i.e. the frames and only
31 * the frames. </p>
32 * <p/>
33 * <p><center> <table border=0> <tr><td nowrap> Total frame CRC</td><td>&nbsp;</td><td>$xx xx xx xx</td></tr> </table>
34 * </center>
35 *
36 * @author Eric Farng
37 * @version $Revision: 1.7 $
38 */
39public class ID3v2_3Frame extends ID3v2_2Frame {
40 
41    protected boolean compression = false;
42    protected boolean encryption = false;
43    protected boolean fileAlterPreservation = false;
44    protected boolean groupingIdentity = false;
45    protected boolean readOnly = false; // @todo implement this read only!
46    // these are flags for each frame them selves
47    protected boolean tagAlterPreservation = false;
48 
49    /**
50     * Creates a new ID3v2_3Frame object.
51     */
52    public ID3v2_3Frame() {
53        setAlterPreservation();
54    }
55 
56    /**
57     * Creates a new ID3v2_3Frame object.
58     */
59    public ID3v2_3Frame(final AbstractID3v2FrameBody body) {
60        super(body);
61        setAlterPreservation();
62    }
63 
64    /**
65     * Creates a new ID3v2_3Frame object.
66     */
67    public ID3v2_3Frame(final ID3v2_3Frame copyObject) {
68        super(copyObject);
69        this.compression = copyObject.compression;
70        this.encryption = copyObject.encryption;
71        this.fileAlterPreservation = copyObject.fileAlterPreservation;
72        this.groupingIdentity = copyObject.groupingIdentity;
73        this.readOnly = copyObject.readOnly;
74        this.tagAlterPreservation = copyObject.tagAlterPreservation;
75    }
76 
77    /**
78     * Creates a new ID3v2_3Frame object.
79     */
80    public ID3v2_3Frame(final boolean readOnly,
81                        final boolean groupingIdentity,
82                        final boolean compression,
83                        final boolean encryption,
84                        final AbstractID3v2FrameBody body) {
85        super(body);
86        this.readOnly = readOnly;
87        this.groupingIdentity = groupingIdentity;
88        this.compression = compression;
89        this.encryption = encryption;
90        setAlterPreservation();
91    }
92 
93    /**
94     * Creates a new ID3v2_4Frame object.
95     */
96    public ID3v2_3Frame(final AbstractID3v2Frame frame) {
97        if (frame instanceof ID3v2_3Frame) {
98            final ID3v2_3Frame f = (ID3v2_3Frame) frame;
99            this.tagAlterPreservation = f.tagAlterPreservation;
100            this.fileAlterPreservation = f.fileAlterPreservation;
101            this.readOnly = f.readOnly;
102            this.groupingIdentity = f.groupingIdentity;
103            this.compression = f.compression;
104            this.encryption = f.encryption;
105        }
106        if (frame instanceof ID3v2_2Frame) {
107            // no variables yet
108        }
109        if (frame.getBody() == null) {
110            // do nothing
111        } else if (TagUtility.isID3v2_3FrameIdentifier(frame.getIdentifier())) {
112            this.setBody((AbstractID3v2FrameBody) TagUtility.copyObject(frame.getBody()));
113//        } else if (TagUtility.isID3v2_4FrameIdentifier(frame.getIdentifier())) {
114//            // @TODO correctly convert tags
115//            this.setBody((AbstractID3v2FrameBody) TagUtility.copyObject(frame.getBody()));
116//        } else if (TagUtility.isID3v2_2FrameIdentifier(frame.getIdentifier())) {
117//            // @TODO correctly convert tags
118//            this.setBody((AbstractID3v2FrameBody) TagUtility.copyObject(frame.getBody()));
119        }
120    }
121 
122    /**
123     * Creates a new ID3v2_3Frame object.
124     */
125    public ID3v2_3Frame(final RandomAccessFile file) throws IOException, InvalidTagException {
126        this.read(file);
127    }
128 
129    public int getSize() {
130        return this.getBody().getSize() + 4 + 2 + 4;
131    }
132 
133    public boolean equals(final Object obj) {
134        if ((obj instanceof ID3v2_3Frame) == false) {
135            return false;
136        }
137        final ID3v2_3Frame id3v2_3Frame = (ID3v2_3Frame) obj;
138        if (this.compression != id3v2_3Frame.compression) {
139            return false;
140        }
141        if (this.encryption != id3v2_3Frame.encryption) {
142            return false;
143        }
144        if (this.fileAlterPreservation != id3v2_3Frame.fileAlterPreservation) {
145            return false;
146        }
147        if (this.groupingIdentity != id3v2_3Frame.groupingIdentity) {
148            return false;
149        }
150        if (this.readOnly != id3v2_3Frame.readOnly) {
151            return false;
152        }
153        if (this.tagAlterPreservation != id3v2_3Frame.tagAlterPreservation) {
154            return false;
155        }
156        return super.equals(obj);
157    }
158 
159    public void read(final RandomAccessFile file) throws IOException, InvalidTagException {
160        byte b;
161        long filePointer;
162        final byte[] buffer = new byte[4];
163 
164        // lets scan for a non-zero byte;
165        do {
166            filePointer = file.getFilePointer();
167            b = file.readByte();
168            org.farng.mp3.id3.AbstractID3v2.incrementPaddingCounter();
169        } while (b == 0);
170        file.seek(filePointer);
171        org.farng.mp3.id3.AbstractID3v2.decrementPaddingCounter();
172 
173        // read the four character identifier
174        file.read(buffer, 0, 4);
175        final String identifier = new String(buffer, 0, 4);
176 
177        // is this a valid identifier?
178        if (isValidID3v2FrameIdentifier(identifier) == false) {
179            file.seek(file.getFilePointer() - 3);
180            throw new InvalidTagException(identifier + " is not a valid ID3v2.30 frame");
181        }
182        filePointer = file.getFilePointer();
183 
184        // skip the 4 byte size
185        file.skipBytes(4);
186 
187        // read the flag bytes
188        file.read(buffer, 0, 2);
189        this.tagAlterPreservation = (buffer[0] & TagConstant.MASK_V23_TAG_ALTER_PRESERVATION) != 0;
190        this.fileAlterPreservation = (buffer[0] & TagConstant.MASK_V23_FILE_ALTER_PRESERVATION) != 0;
191        this.readOnly = (buffer[0] & TagConstant.MASK_V23_READ_ONLY) != 0;
192        this.compression = (buffer[1] & TagConstant.MASK_V23_COMPRESSION) != 0;
193        this.encryption = (buffer[1] & TagConstant.MASK_V23_ENCRYPTION) != 0;
194        this.groupingIdentity = (buffer[1] & TagConstant.MASK_V23_GROUPING_IDENTITY) != 0;
195        file.seek(filePointer);
196        this.setBody(readBody(identifier, file));
197    }
198 
199    public void write(final RandomAccessFile file) throws IOException {
200        final long filePointer;
201        final byte[] buffer = new byte[4];
202        final String str = TagUtility.truncate(getIdentifier(), 4);
203        for (int i = 0; i < str.length(); i++) {
204            buffer[i] = (byte) str.charAt(i);
205        }
206        file.write(buffer, 0, str.length());
207        filePointer = file.getFilePointer();
208 
209        // skip the size bytes
210        file.skipBytes(4);
211        setAlterPreservation();
212        buffer[0] = 0;
213        buffer[1] = 0;
214        if (this.tagAlterPreservation) {
215            buffer[0] |= TagConstant.MASK_V23_TAG_ALTER_PRESERVATION;
216        }
217        if (this.fileAlterPreservation) {
218            buffer[0] |= TagConstant.MASK_V23_FILE_ALTER_PRESERVATION;
219        }
220        if (this.readOnly) {
221            buffer[0] |= TagConstant.MASK_V23_READ_ONLY;
222        }
223        if (this.compression) {
224            buffer[1] |= TagConstant.MASK_V23_COMPRESSION;
225        }
226        if (this.encryption) {
227            buffer[1] |= TagConstant.MASK_V23_ENCRYPTION;
228        }
229        if (this.groupingIdentity) {
230            buffer[1] |= TagConstant.MASK_V23_GROUPING_IDENTITY;
231        }
232        file.write(buffer, 0, 2);
233        file.seek(filePointer);
234        this.getBody().write(file);
235    }
236 
237    protected void setAlterPreservation() {
238        final String str = getIdentifier();
239        if (str.equals("ETCO") ||
240            str.equals("EQUA") ||
241            str.equals("MLLT") ||
242            str.equals("POSS") ||
243            str.equals("SYLT") ||
244            str.equals("SYTC") ||
245            str.equals("RVAD") ||
246            str.equals("TENC") ||
247            str.equals("TLEN") ||
248            str.equals("TSIZ")) {
249            this.tagAlterPreservation = false;
250            this.fileAlterPreservation = true;
251        } else {
252            this.tagAlterPreservation = false;
253            this.fileAlterPreservation = true;
254        }
255    }
256}

[all classes][org.farng.mp3.id3]
EMMA 2.0.5312 (C) Vladimir Roubtsov