Fields Summary |
---|
public static final long | DWORD_MAXVALUEMaximum value for WORD. |
private static final Logger | LOGGERLogger instance. |
public static final int | MAX_LANG_INDEXThe maximum language index allowed. (exclusive) |
public static final int | MAX_STREAM_NUMBERMaximum stream number. (inclusive) |
public static final BigInteger | QWORD_MAXVALUEMaximum value for a QWORD value (64 bit unsigned).
|
public static final int | TYPE_BINARYConstant for the metadata descriptor-type for binary data. |
public static final int | TYPE_BOOLEANConstant for the metadata descriptor-type for booleans. |
public static final int | TYPE_DWORDConstant for the metadata descriptor-type for DWORD (32-bit unsigned).
|
public static final int | TYPE_GUIDConstant for the metadata descriptor-type for GUIDs (128-bit).
|
public static final int | TYPE_QWORDConstant for the metadata descriptor-type for QWORD (64-bit unsinged).
|
public static final int | TYPE_STRINGConstant for the metadata descriptor-type for Strings. |
public static final int | TYPE_WORDConstant for the metadata descriptor-type for WORD (16-bit unsigned).
|
public static final int | WORD_MAXVALUEMaximum value for WORD. |
private final ContainerType | containerTypeStores the containerType of the descriptor. |
private byte[] | contentThe binary representation of the value. |
private int | descriptorTypeThis field shows the type of the metadata descriptor.
|
private int | languageIndexthe index of the language in the {@linkplain LanguageList language list}
this descriptor applies to.
|
private final String | nameThe name of the metadata descriptor. |
private int | streamNumberThe number of the stream, this descriptor applies to.
|
Methods Summary |
---|
public java.math.BigInteger | asNumber()Converts the descriptors value into a number if possible.
A boolean will be converted to "1" if true ,
otherwise "0".
String will be interpreted as number with radix "10".
Binary data will be interpreted as the default WORD,DWORD or QWORD binary
representation, but only if the data does not exceed 8 bytes. This
precaution is done to prevent creating a number of a multi kilobyte
image.
A GUID cannot be converted in any case.
BigInteger result = null;
switch (this.descriptorType) {
case TYPE_BOOLEAN:
case TYPE_WORD:
case TYPE_DWORD:
case TYPE_QWORD:
case TYPE_BINARY:
if (this.content.length > 8) {
throw new NumberFormatException(
"Binary data would exceed QWORD");
}
break;
case TYPE_GUID:
throw new NumberFormatException(
"GUID cannot be converted to a number.");
case TYPE_STRING:
result = new BigInteger(getString(), 10);
break;
default:
throw new IllegalStateException();
}
if (result == null) {
final byte[] copy = new byte[this.content.length];
for (int i = 0; i < copy.length; i++) {
copy[i] = this.content[this.content.length - (i + 1)];
}
result = new BigInteger(1, copy);
}
return result;
|
public java.lang.Object | clone()(overridden)
return super.clone();
|
public int | compareTo(org.jaudiotagger.audio.asf.data.MetadataDescriptor other){@inheritDoc}
return getName().compareTo(other.getName());
|
public org.jaudiotagger.audio.asf.data.MetadataDescriptor | createCopy()This method creates a copy of the current object.
All data will be copied, too.
final MetadataDescriptor result = new MetadataDescriptor(
this.containerType, this.name, this.descriptorType,
this.streamNumber, this.languageIndex);
result.content = getRawData();
return result;
|
public boolean | equals(java.lang.Object obj)(overridden)
boolean result = false;
if (obj instanceof MetadataDescriptor) {
if (obj == this) {
result = true;
} else {
final MetadataDescriptor other = (MetadataDescriptor) obj;
result = other.getName().equals(getName())
&& other.descriptorType == this.descriptorType
&& other.languageIndex == this.languageIndex
&& other.streamNumber == this.streamNumber
&& Arrays.equals(this.content, other.content);
}
}
return result;
|
public boolean | getBoolean()Returns the value of the MetadataDescriptor as a Boolean.
If no Conversion is Possible false is returned.
true if first byte of {@link #content}is not zero.
return this.content.length > 0 && this.content[0] != 0;
|
public byte[] | getBytes()This method will return a byte array, which can directly be written into
an "Extended Content Description"-chunk.
final ByteArrayOutputStream result = new ByteArrayOutputStream();
try {
writeInto(result, this.containerType);
} catch (final IOException e) {
LOGGER.warning(e.getMessage());
}
return result.toByteArray();
|
public ContainerType | getContainerType()Returns the container type this descriptor ist restricted to.
return this.containerType;
|
public int | getCurrentAsfSize(ContainerType type)Returns the size (in bytes) this descriptor will take when written to an
ASF file.
/*
* 2 bytes name length, 2 bytes name zero term, 2 bytes type, 2 bytes
* content length
*/
int result = 8;
if (type != ContainerType.EXTENDED_CONTENT) {
// Stream number and language index (respectively reserved field).
// And +2 bytes, because data type is 32 bit, not 16
result += 6;
}
result += getName().length() * 2;
if (this.getType() == TYPE_BOOLEAN) {
result += 2;
if (type == ContainerType.EXTENDED_CONTENT) {
// Extended content description boolean values are stored with
// 32-bit
result += 2;
}
} else {
result += this.content.length;
if (TYPE_STRING == this.getType()) {
result += 2; // zero term of content string.
}
}
return result;
|
public GUID | getGuid()Returns the GUID value, if content could represent one.
GUID result = null;
if (getType() == TYPE_GUID && this.content.length == GUID.GUID_LENGTH) {
result = new GUID(this.content);
}
return result;
|
public int | getLanguageIndex()Returns the index of the language that is referred (see
{@link LanguageList}):
return this.languageIndex;
|
public java.lang.String | getName()This method returns the name of the metadata descriptor.
return this.name;
|
public long | getNumber()This method returns the value of the metadata descriptor as a long.
Converts the needed amount of byte out of {@link #content}to a number.
Only possible if {@link #getType()}equals on of the following:
int bytesNeeded;
switch (getType()) {
case TYPE_BOOLEAN:
bytesNeeded = 1;
break;
case TYPE_DWORD:
bytesNeeded = 4;
break;
case TYPE_QWORD:
bytesNeeded = 8;
break;
case TYPE_WORD:
bytesNeeded = 2;
break;
default:
throw new UnsupportedOperationException(
"The current type doesn't allow an interpretation as a number. ("
+ getType() + ")");
}
if (bytesNeeded > this.content.length) {
throw new IllegalStateException(
"The stored data cannot represent the type of current object.");
}
long result = 0;
for (int i = 0; i < bytesNeeded; i++) {
result |= (((long) this.content[i] & 0xFF) << (i * 8));
}
return result;
|
public byte[] | getRawData()This method returns a copy of the content of the descriptor.
final byte[] copy = new byte[this.content.length];
System.arraycopy(this.content, 0, copy, 0, this.content.length);
return copy;
|
public int | getRawDataSize()Returns the size (in bytes) the binary representation of the content
uses. (length of {@link #getRawData()})
return this.content.length;
|
public int | getStreamNumber()Returns the stream number this descriptor applies to.
return this.streamNumber;
|
public java.lang.String | getString()Returns the value of the MetadataDescriptor as a String.
String result = null;
switch (getType()) {
case TYPE_BINARY:
result = "binary data";
break;
case TYPE_BOOLEAN:
result = String.valueOf(getBoolean());
break;
case TYPE_GUID:
result = getGuid() == null ? "Invalid GUID" : getGuid().toString();
break;
case TYPE_QWORD:
case TYPE_DWORD:
case TYPE_WORD:
result = String.valueOf(getNumber());
break;
case TYPE_STRING:
try {
result = new String(this.content, "UTF-16LE");
} catch (final UnsupportedEncodingException e) {
LOGGER.warning(e.getMessage());
}
break;
default:
throw new IllegalStateException("Current type is not known.");
}
return result;
|
public int | getType()Returns the type of the metadata descriptor.
return this.descriptorType;
|
public int | hashCode(){@inheritDoc}
return this.name.hashCode();
|
public boolean | isEmpty()This method checks if the binary data is empty.
Disregarding the type of the descriptor its content is stored as a byte
array.
return this.content.length == 0;
|
public void | setBinaryValue(byte[] data)Sets the Value of the current metadata descriptor.
Using this method will change {@link #descriptorType}to
{@link #TYPE_BINARY}.
this.containerType.assertConstraints(this.name, data,
this.descriptorType, this.streamNumber, this.languageIndex);
this.content = data.clone();
this.descriptorType = TYPE_BINARY;
|
public void | setBooleanValue(boolean value)Sets the Value of the current metadata descriptor.
Using this method will change {@link #descriptorType}to
{@link #TYPE_BOOLEAN}.
this.content = new byte[] { value ? (byte) 1 : 0 };
this.descriptorType = TYPE_BOOLEAN;
|
public void | setDWordValue(long value)Sets the Value of the current metadata descriptor.
Using this method will change {@link #descriptorType}to
{@link #TYPE_DWORD}.
if (value < 0 || value > DWORD_MAXVALUE) {
throw new IllegalArgumentException("value out of range (0-"
+ DWORD_MAXVALUE + ")");
}
this.content = Utils.getBytes(value, 4);
this.descriptorType = TYPE_DWORD;
|
public void | setGUIDValue(GUID value)Sets the value of the metadata descriptor.
Using this method will change {@link #descriptorType} to
{@link #TYPE_GUID}
this.containerType.assertConstraints(this.name, value.getBytes(),
TYPE_GUID, this.streamNumber, this.languageIndex);
this.content = value.getBytes();
this.descriptorType = TYPE_GUID;
|
public void | setLanguageIndex(int language)Sets the index of the referred language (see {@link LanguageList}).
Consider: The {@linkplain #containerType requirements} must be
held.
this.containerType.assertConstraints(this.name, this.content,
this.descriptorType, this.streamNumber, language);
this.languageIndex = language;
|
public void | setQWordValue(java.math.BigInteger value)Sets the Value of the current metadata descriptor.
Using this method will change {@link #descriptorType}to
{@link #TYPE_QWORD}
if (value == null) {
throw new NumberFormatException("null");
}
if (BigInteger.ZERO.compareTo(value) > 0) {
throw new IllegalArgumentException(
"Only unsigned values allowed (no negative)");
}
if (MetadataDescriptor.QWORD_MAXVALUE.compareTo(value) < 0) {
throw new IllegalArgumentException(
"Value exceeds QWORD (64 bit unsigned)");
}
this.content = new byte[8];
final byte[] valuesBytes = value.toByteArray();
if (valuesBytes.length <= 8) {
for (int i = valuesBytes.length - 1; i >= 0; i--) {
this.content[valuesBytes.length - (i + 1)] = valuesBytes[i];
}
} else {
/*
* In case of 64-Bit set
*/
Arrays.fill(this.content, (byte) 0xFF);
}
this.descriptorType = TYPE_QWORD;
|
public void | setQWordValue(long value)Sets the Value of the current metadata descriptor.
Using this method will change {@link #descriptorType}to
{@link #TYPE_QWORD}
if (value < 0) {
throw new IllegalArgumentException("value out of range (0-"
+ MetadataDescriptor.QWORD_MAXVALUE.toString() + ")");
}
this.content = Utils.getBytes(value, 8);
this.descriptorType = TYPE_QWORD;
|
public void | setStreamNumber(int stream)Sets the stream number the descriptor applies to.
Consider: The {@linkplain #containerType requirements} must be
held.
this.containerType.assertConstraints(this.name, this.content,
this.descriptorType, stream, this.languageIndex);
this.streamNumber = stream;
|
public void | setString(java.lang.String value)This method converts the given string value into the current
{@linkplain #getType() data type}.
try {
switch (getType()) {
case TYPE_BINARY:
throw new IllegalArgumentException(
"Cannot interpret binary as string.");
case TYPE_BOOLEAN:
setBooleanValue(Boolean.parseBoolean(value));
break;
case TYPE_DWORD:
setDWordValue(Long.parseLong(value));
break;
case TYPE_QWORD:
setQWordValue(new BigInteger(value, 10));
break;
case TYPE_WORD:
setWordValue(Integer.parseInt(value));
break;
case TYPE_GUID:
setGUIDValue(GUID.parseGUID(value));
break;
case TYPE_STRING:
setStringValue(value);
break;
default:
// new Type added but not handled.
throw new IllegalStateException();
}
} catch (final NumberFormatException nfe) {
throw new IllegalArgumentException(
"Value cannot be parsed as Number or is out of range (\""
+ value + "\")", nfe);
}
|
public void | setStringValue(java.lang.String value)Sets the Value of the current metadata descriptor.
Using this method will change {@link #descriptorType}to
{@link #TYPE_STRING}.
if (value == null) {
this.content = new byte[0];
} else {
final byte[] tmp = Utils.getBytes(value, AsfHeader.ASF_CHARSET);
if (getContainerType().isWithinValueRange(tmp.length)) {
// Everything is fine here, data can be stored.
this.content = tmp;
} else {
// Normally a size violation, check if JAudiotagger my truncate
// the string
if (TagOptionSingleton.getInstance()
.isTruncateTextWithoutErrors()) {
// truncate the string
final int copyBytes = (int) getContainerType()
.getMaximumDataLength().longValue();
this.content = new byte[copyBytes % 2 == 0 ? copyBytes
: copyBytes - 1];
System.arraycopy(tmp, 0, this.content, 0,
this.content.length);
} else {
// We may not truncate, so its an error
throw new IllegalArgumentException(
ErrorMessage.WMA_LENGTH_OF_DATA_IS_TOO_LARGE
.getMsg(tmp.length, getContainerType()
.getMaximumDataLength(),
getContainerType()
.getContainerGUID()
.getDescription()));
}
}
}
this.descriptorType = TYPE_STRING;
|
public void | setWordValue(int value)Sets the Value of the current metadata descriptor.
Using this method will change {@link #descriptorType}to
{@link #TYPE_WORD}
if (value < 0 || value > WORD_MAXVALUE) {
throw new IllegalArgumentException("value out of range (0-"
+ WORD_MAXVALUE + ")");
}
this.content = Utils.getBytes(value, 2);
this.descriptorType = TYPE_WORD;
|
public java.lang.String | toString()(overridden)
return getName()
+ " : "
+ new String[] { "String: ", "Binary: ", "Boolean: ",
"DWORD: ", "QWORD:", "WORD:", "GUID:" }[this.descriptorType]
+ getString() + " (language: " + this.languageIndex
+ " / stream: " + this.streamNumber + ")";
|
public int | writeInto(java.io.OutputStream out, ContainerType contType)Writes this descriptor into the specified output stream.
final int size = getCurrentAsfSize(contType);
/*
* Booleans are stored as one byte, if a boolean is written, the data
* must be converted according to the container type.
*/
byte[] binaryData;
if (this.descriptorType == TYPE_BOOLEAN) {
binaryData = new byte[contType == ContainerType.EXTENDED_CONTENT ? 4
: 2];
binaryData[0] = (byte) (getBoolean() ? 1 : 0);
} else {
binaryData = this.content;
}
// for Metadata objects the stream number and language index
if (contType != ContainerType.EXTENDED_CONTENT) {
Utils.writeUINT16(getLanguageIndex(), out);
Utils.writeUINT16(getStreamNumber(), out);
}
Utils.writeUINT16(getName().length() * 2 + 2, out);
// The name for the metadata objects come later
if (contType == ContainerType.EXTENDED_CONTENT) {
out.write(Utils.getBytes(getName(), AsfHeader.ASF_CHARSET));
out.write(AsfHeader.ZERO_TERM);
}
// type and content len follow up are identical
final int type = getType();
Utils.writeUINT16(type, out);
int contentLen = binaryData.length;
if (TYPE_STRING == type) {
contentLen += 2; // Zero Term
}
if (contType == ContainerType.EXTENDED_CONTENT) {
Utils.writeUINT16(contentLen, out);
} else {
Utils.writeUINT32(contentLen, out);
}
// Metadata objects now write their descriptor name
if (contType != ContainerType.EXTENDED_CONTENT) {
out.write(Utils.getBytes(getName(), AsfHeader.ASF_CHARSET));
out.write(AsfHeader.ZERO_TERM);
}
// The content.
out.write(binaryData);
if (TYPE_STRING == type) {
out.write(AsfHeader.ZERO_TERM);
}
return size;
|