/*
* Digital Audio Access Protocol (DAAP) Library
* Copyright (C) 2004-2010 Roger Kapsi
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ardverk.daap;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.ardverk.daap.chunks.BooleanChunk;
import org.ardverk.daap.chunks.Chunk;
import org.ardverk.daap.chunks.DateChunk;
import org.ardverk.daap.chunks.LongChunk;
import org.ardverk.daap.chunks.SByteChunk;
import org.ardverk.daap.chunks.SShortChunk;
import org.ardverk.daap.chunks.StringChunk;
import org.ardverk.daap.chunks.UByteChunk;
import org.ardverk.daap.chunks.UIntChunk;
import org.ardverk.daap.chunks.UShortChunk;
import org.ardverk.daap.chunks.impl.ContainerItemId;
import org.ardverk.daap.chunks.impl.HasVideo;
import org.ardverk.daap.chunks.impl.ITMSArtistId;
import org.ardverk.daap.chunks.impl.ITMSComposerId;
import org.ardverk.daap.chunks.impl.ITMSGenreId;
import org.ardverk.daap.chunks.impl.ITMSPlaylistId;
import org.ardverk.daap.chunks.impl.ITMSSongId;
import org.ardverk.daap.chunks.impl.ITMSStorefrontId;
import org.ardverk.daap.chunks.impl.ItemId;
import org.ardverk.daap.chunks.impl.ItemKind;
import org.ardverk.daap.chunks.impl.ItemName;
import org.ardverk.daap.chunks.impl.NormVolume;
import org.ardverk.daap.chunks.impl.PersistentId;
import org.ardverk.daap.chunks.impl.Podcast;
import org.ardverk.daap.chunks.impl.SongAlbum;
import org.ardverk.daap.chunks.impl.SongArtist;
import org.ardverk.daap.chunks.impl.SongBeatsPerMinute;
import org.ardverk.daap.chunks.impl.SongBitrate;
import org.ardverk.daap.chunks.impl.SongCategory;
import org.ardverk.daap.chunks.impl.SongCodecSubtype;
import org.ardverk.daap.chunks.impl.SongCodecType;
import org.ardverk.daap.chunks.impl.SongComment;
import org.ardverk.daap.chunks.impl.SongCompilation;
import org.ardverk.daap.chunks.impl.SongComposer;
import org.ardverk.daap.chunks.impl.SongContentDescription;
import org.ardverk.daap.chunks.impl.SongContentRating;
import org.ardverk.daap.chunks.impl.SongDataKind;
import org.ardverk.daap.chunks.impl.SongDataUrl;
import org.ardverk.daap.chunks.impl.SongDateAdded;
import org.ardverk.daap.chunks.impl.SongDateModified;
import org.ardverk.daap.chunks.impl.SongDescription;
import org.ardverk.daap.chunks.impl.SongDisabled;
import org.ardverk.daap.chunks.impl.SongDiscCount;
import org.ardverk.daap.chunks.impl.SongDiscNumber;
import org.ardverk.daap.chunks.impl.SongEqPreset;
import org.ardverk.daap.chunks.impl.SongFormat;
import org.ardverk.daap.chunks.impl.SongGenre;
import org.ardverk.daap.chunks.impl.SongGrouping;
import org.ardverk.daap.chunks.impl.SongKeywords;
import org.ardverk.daap.chunks.impl.SongLongDescription;
import org.ardverk.daap.chunks.impl.SongRelativeVolume;
import org.ardverk.daap.chunks.impl.SongSampleRate;
import org.ardverk.daap.chunks.impl.SongSize;
import org.ardverk.daap.chunks.impl.SongStartTime;
import org.ardverk.daap.chunks.impl.SongStopTime;
import org.ardverk.daap.chunks.impl.SongTime;
import org.ardverk.daap.chunks.impl.SongTrackCount;
import org.ardverk.daap.chunks.impl.SongTrackNumber;
import org.ardverk.daap.chunks.impl.SongUserRating;
import org.ardverk.daap.chunks.impl.SongYear;
/**
* There isn't much to say: a Song is a Song.
* <p>
* Note: although already mentioned in StringChunk I'd like to point out that
* <code>null</code> is a valid value for DAAP. Use it to reset Strings. See
* StringChunk for more information!
* </p>
*
* @author Roger Kapsi
*/
public class Song {
/** songId is an 32bit unsigned value! */
private static final AtomicLong SONG_ID = new AtomicLong(1);
private static final SongFormat FORMAT
= new SongFormat(SongFormat.MP3);
private static final SongSampleRate SAMPLE_RATE
= new SongSampleRate(SongSampleRate.KHZ_44100);
private final Map<String, Chunk> chunks = new HashMap<String, Chunk>();
private final ItemKind itemKind = new ItemKind(ItemKind.AUDIO);
private final ItemId itemId = new ItemId(SONG_ID.getAndIncrement());
private final ItemName itemName = new ItemName();
private final ContainerItemId containerItemId = new ContainerItemId();
private final PersistentId persistentId = new PersistentId();
private SongAlbum album;
private SongArtist artist;
private SongBeatsPerMinute bpm;
private SongBitrate bitrate;
private SongComment comment;
private SongCompilation compilation;
private SongComposer composer;
private SongDataKind dataKind;
private SongDataUrl dataUrl;
private SongDateAdded dateAdded;
private SongDateModified dateModified;
private SongDescription description;
private SongDisabled disabled;
private SongDiscCount discCount;
private SongDiscNumber discNumber;
private SongEqPreset eqPreset;
private SongFormat format;
private SongGenre genre;
private SongRelativeVolume relativeVolume;
private SongSampleRate sampleRate;
private SongSize size;
private SongStartTime startTime;
private SongStopTime stopTime;
private SongTime time;
private SongTrackCount trackCount;
private SongTrackNumber trackNumber;
private SongUserRating userRating;
private SongYear year;
private SongGrouping grouping;
private NormVolume normVolume;
private SongCodecType codecType;
private SongCodecSubtype codecSubtype;
private ITMSArtistId itmsArtistId;
private ITMSComposerId itmsComposerId;
private ITMSGenreId itmsGenreId;
private ITMSPlaylistId itmsPlaylistId;
private ITMSStorefrontId itmsStorefrontId;
private ITMSSongId itmsSongId;
// @since iTunes 5.0
private Podcast podcast;
private SongCategory category;
private SongContentDescription contentDescription;
private SongContentRating contentRating;
private SongKeywords keywords;
private SongLongDescription longDescription;
// @since iTunes 6.0.2
private HasVideo hasVideo;
/** An arbitrary Object (most likely a File) */
private Object attachment;
/**
* Creates a new Song
*/
public Song() {
persistentId.setValue(itemId.getValue());
containerItemId.setValue(itemId.getValue());
init();
}
/**
* Creates a new Song with the provided name
*/
public Song(String name) {
this();
itemName.setValue(name);
}
private void init() {
addChunk(itemKind);
addChunk(itemName);
addChunk(itemId);
addChunk(containerItemId);
// Some clients do not init format (implicit mp3)
// and use uninitialized garbage instead
addChunk(FORMAT);
// VLC requires the sample rate
addChunk(SAMPLE_RATE);
}
/**
* Returns the unique id of this song
*/
protected long getItemId() {
return itemId.getUnsignedValue();
}
/**
* Returns the id of this Songs container. Note: same as getId()
*/
protected long getContainerId() {
return containerItemId.getUnsignedValue();
}
/**
* Returns the name of this Song
*/
public String getName() {
return getStringValue(itemName);
}
/**
* Sets the name of this Song
*/
public void setName(Transaction txn, String itemName) {
setStringValue(txn, "itemName", itemName);
}
/**
* Sets the album of this Song
*/
public void setAlbum(Transaction txn, String album) {
setStringValue(txn, "album", album);
}
/**
* Returns the album of this Song
*/
public String getAlbum() {
return getStringValue(album);
}
/**
* Sets the artist of this Song
*/
public void setArtist(Transaction txn, String artist) {
setStringValue(txn, "artist", artist);
}
/**
* Returns the artist of this Song
*/
public String getArtist() {
return getStringValue(artist);
}
/**
* Sets the beats per minute of this Song
*/
public void setBeatsPerMinute(Transaction txn, int bpm) {
setUShortValue(txn, "bpm", bpm);
}
/**
* Returns the beats per minute of this Song
*/
public int getBeatsPerMinute() {
return getUShortValue(bpm);
}
/**
* Sets the bitrate of this Song
*/
public void setBitrate(Transaction txn, int bitrate) {
setUShortValue(txn, "bitrate", bitrate);
}
/**
* Returns the bitrate of this Song
*/
public int getBitrate() {
return getUShortValue(bitrate);
}
/**
* Sets the comment of this Song
*/
public void setComment(Transaction txn, String comment) {
setStringValue(txn, "comment", comment);
}
/**
* Returns the comment of this Song
*/
public String getComment() {
return getStringValue(comment);
}
/**
* Sets if this Song is a compilation
*/
public void setCompilation(Transaction txn, boolean compilation) {
setBooleanValue(txn, "compilation", compilation);
}
/**
* Returns <tt>true</tt> if this Song is a compilation
*/
public boolean isCompilation() {
return getBooleanValue(compilation);
}
/**
* Sets the composer of this Song
**/
public void setComposer(Transaction txn, String composer) {
setStringValue(txn, "composer", composer);
}
/**
* Returns the composer of this Song
*/
public String getComposer() {
return getStringValue(composer);
}
/**
* Sets whether this Song is a Radio or a DAAP stream. See SongDataKind for
* more information. Note: you must set the DataUrl with setDataUrl() if
* dataKind is Radio!
*/
public void setDataKind(Transaction txn, int dataKind) {
setUByteValue(txn, "dataKind", dataKind);
}
/**
* Returns the kind of this Song
*/
public int getDataKind() {
return getUByteValue(dataKind);
}
/**
* Sets the URL of this Song
*/
public void setDataUrl(Transaction txn, String dataUrl) {
setStringValue(txn, "dataUrl", dataUrl);
}
/**
* Returns the URL of this Song
*/
public String getDataUrl() {
return getStringValue(dataUrl);
}
/**
* Sets the date when this Song was added to the Library. Note: the date is
* in seconds since 1970.
* <code>(int)(System.currentTimeMillis()/1000)</code>
*/
public void setDateAdded(Transaction txn, long dateAdded) {
setDateValue(txn, "dateAdded", dateAdded);
}
/**
* Returns the date when this Song was added to the Library
*/
public long getDateAdded() {
return getDateValue(dateAdded);
}
/**
* Sets the date when this Song was modified. Note: the date is in seconds
* since 1970. <code>(int)(System.currentTimeMillis()/1000)</code>
*/
public void setDateModified(Transaction txn, long dateModified) {
setDateValue(txn, "dateModified", dateModified);
}
/**
* Returns the date when this song was modified
*/
public long getDateModified() {
return getDateValue(dateModified);
}
/**
* Sets the description of this Song. Note: the description of a Song is its
* file format. The description of a MP3 file is for example 'MPEG Audio
* file'. See SongDescription for more information.
*/
public void setDescription(Transaction txn, String description) {
setStringValue(txn, "description", description);
}
/**
* Returns the description of this Song
*/
public String getDescription() {
return getStringValue(description);
}
/**
* Sets if this Song is either disabled or enabled. This is indicated in
* iTunes by the small checkbox next to the Song name.
*/
public void setDisabled(Transaction txn, boolean disabled) {
setBooleanValue(txn, "disabled", disabled);
}
/**
* Returns <tt>true</tt> if this Song is disabled
*/
public boolean isDisabled() {
return getBooleanValue(disabled);
}
/**
* Sets the number of discs of this Song
*/
public void setDiscCount(Transaction txn, int discCount) {
setUShortValue(txn, "discCount", discCount);
}
/**
* Returns the number of discs
*/
public int getDiscCount() {
return getUShortValue(discCount);
}
/**
* Sets the disc number of this Song
*/
public void setDiscNumber(Transaction txn, int discNumber) {
setUShortValue(txn, "discNumber", discNumber);
}
/**
* Returns the disc number of this Song
*/
public int getDiscNumber() {
return getUShortValue(discNumber);
}
/**
* Sets the equalizer of this Song. Note: See SongEqPreset for more
* information
*/
public void setEqPreset(Transaction txn, String eqPreset) {
setStringValue(txn, "eqPreset", eqPreset);
}
/**
* Returns the equalizer of this Song
*/
public String getEqPreset() {
return getStringValue(eqPreset);
}
/**
* Sets the format of this Song. Note: See SongFormat for more information
*/
public void setFormat(Transaction txn, String format) {
setStringValue(txn, "format", format);
}
/**
* Returns the format of this Song
*/
public String getFormat() {
return getStringValue(format);
}
/**
* Sets the genre of this Song. Note: See SongGenre for more information
*/
public void setGenre(Transaction txn, String genre) {
setStringValue(txn, "genre", genre);
}
/**
* Returns the genre of this Song
*/
public String getGenre() {
return getStringValue(genre);
}
/**
* Unknown purpose
*/
public void setRelativeVolume(Transaction txn, int relativeVolume) {
setSByteValue(txn, "relativeVolume", relativeVolume);
}
/**
* Unknown purpose
*/
public int getRelativeVolume() {
return getSByteValue(relativeVolume);
}
/**
* Sets the sample rate of this Song in kHz
*/
public void setSampleRate(Transaction txn, long sampleRate) {
setUIntValue(txn, "sampleRate", sampleRate);
}
/**
* Returns the sample rate of this Song
*/
public long getSampleRate() {
return getUIntValue(sampleRate);
}
/**
* Sets the file size of this Song
*/
public void setSize(Transaction txn, long size) {
setUIntValue(txn, "size", size);
}
/**
* Returns the file size of this Song
*/
public long getSize() {
return getUIntValue(size);
}
/**
* Sets the start time of this Song in <tt>milliseconds</tt>.
*/
public void setStartTime(Transaction txn, long startTime) {
setUIntValue(txn, "startTime", startTime);
}
/**
* Returns the start time of this Song
*/
public long getStartTime() {
return getUIntValue(startTime);
}
/**
* Sets the stop time of this Song in <tt>milliseconds</tt>.
*/
public void setStopTime(Transaction txn, long stopTime) {
setUIntValue(txn, "stopTime", stopTime);
}
/**
* Returns the stop time of this Song
*/
public long getStopTime() {
return getUIntValue(stopTime);
}
/**
* Sets the time (length) of this Song in <tt>milliseconds</tt>.
*/
public void setTime(Transaction txn, long time) {
setUIntValue(txn, "time", time);
}
/**
* Returns the time (length) of this Song
*/
public long getTime() {
return getUIntValue(time);
}
/**
* Sets the track count of this Song
*/
public void setTrackCount(Transaction txn, int trackCount) {
setUShortValue(txn, "trackCount", trackCount);
}
/**
* Returns the track count of this Song
*/
public int getTrackCount() {
return getUShortValue(trackCount);
}
/**
* Sets the track number of this Song
*/
public void setTrackNumber(Transaction txn, int trackNumber) {
setUShortValue(txn, "trackNumber", trackNumber);
}
/**
* Returns the track number of this Song
*/
public int getTrackNumber() {
return getUShortValue(trackNumber);
}
/**
* Sets the user rating of this Song. Note: See SongUserRating for more
* informations
*/
public void setUserRating(Transaction txn, int userRating) {
setUByteValue(txn, "userRating", userRating);
}
/**
* Returns the user rating of this Song
*/
public int getUserRating() {
return getUByteValue(userRating);
}
/**
* Sets the year of this Song
*/
public void setYear(Transaction txn, int year) {
setUShortValue(txn, "year", year);
}
/**
* Returns the year of this Song
*/
public int getYear() {
return getUShortValue(year);
}
/**
* Sets the grouping of this Song
*/
public void setGrouping(Transaction txn, String grouping) {
setStringValue(txn, "grouping", grouping);
}
/**
* Returns the grouping of this Song
*/
public String getGrouping() {
return getStringValue(grouping);
}
/**
* Sets the ITMS Artist Id
*/
public void setITMSArtistId(Transaction txn, long itmsArtistId) {
setUIntValue(txn, "itmsArtistId", itmsArtistId);
}
/**
* Returns the ITMS Artist Id
*/
public long getITMSArtistId() {
return getUIntValue(itmsArtistId);
}
/**
* Sets the ITMS Composer Id
*/
public void setITMSComposerId(Transaction txn, long itmsComposerId) {
setUIntValue(txn, "itmsComposerId", itmsComposerId);
}
/**
* Returns the ITMS Composer Id
*/
public long getITMSComposerId() {
return getUIntValue(itmsComposerId);
}
/**
* Sets the ITMS Genre Id
*/
public void setITMSGenreId(Transaction txn, long itmsGenreId) {
setUIntValue(txn, "itmsGenreId", itmsGenreId);
}
/**
* Returns the ITMS Genre Id
*/
public long getITMSGenreId() {
return getUIntValue(itmsGenreId);
}
/**
* Sets the ITMS Playlist (=Album) Id
*/
public void setITMSPlaylistId(Transaction txn, long itmsPlaylistId) {
setUIntValue(txn, "itmsPlaylistId", itmsPlaylistId);
}
/**
* Returns the ITMS Playlist (=Album) Id
*/
public long getITMSPlaylistId() {
return getUIntValue(itmsPlaylistId);
}
/**
* Sets the ITMS Storefront Id
*/
public void setITMSStorefrontId(Transaction txn, long itmsStorefrontId) {
setUIntValue(txn, "itmsStorefrontId", itmsStorefrontId);
}
/**
* Returns the ITMS Storefront Id
*/
public long getITMSStrorefrontId() {
return getUIntValue(itmsStorefrontId);
}
/**
* Sets the ITMS Song Id
*/
public void setITMSSongId(Transaction txn, long itmsSongId) {
setUIntValue(txn, "itmsSongId", itmsSongId);
}
/**
* Returns the ITMS Song Id
*/
public long getITMSSongId() {
return getUIntValue(itmsSongId);
}
/**
* Sets the codec type
*/
public void setCodecType(Transaction txn, long codecType) {
setUIntValue(txn, "codecType", codecType);
}
/**
* Returns the codec type
*/
public long getCodecType() {
return getUIntValue(codecType);
}
/**
* Sets the codec subtype
*/
public void setCodecSubtype(Transaction txn, long codecSubtype) {
setUIntValue(txn, "codecSubtype", codecSubtype);
}
/**
* Returns the codec subtype
*/
public long getCodecSubtype() {
return getUIntValue(codecSubtype);
}
/**
* Sets the norm volume
*/
public void setNormVolume(Transaction txn, long normVolume) {
setUIntValue(txn, "normVolume", normVolume);
}
/**
* Returns the norm volume of this Song
*/
public long getNormVolume() {
return getUIntValue(normVolume);
}
/**
*
*/
public void setPodcast(Transaction txn, boolean podcast) {
setBooleanValue(txn, "podcast", podcast);
}
/**
*
*/
public boolean isPodcast() {
return getBooleanValue(podcast);
}
/**
*
*/
public void setCategory(Transaction txn, String category) {
setStringValue(txn, "category", category);
}
/**
*
*/
public String getCategory() {
return getStringValue(category);
}
/**
*
*/
public void setContentDescription(Transaction txn, String contentDescription) {
setStringValue(txn, "contentDescription", contentDescription);
}
/**
*
*/
public String getContentDescription() {
return getStringValue(contentDescription);
}
/**
*
*/
public void setContentRating(Transaction txn, int contentRating) {
setUByteValue(txn, "contentRating", contentRating);
}
/**
*
*/
public int getContentRating() {
return getUByteValue(contentRating);
}
/**
*
*/
public void setKeywords(Transaction txn, String keywords) {
setStringValue(txn, "keywords", keywords);
}
/**
*
*/
public String getKeywords() {
return getStringValue(keywords);
}
/**
*
*/
public void setLongDescription(Transaction txn, String longDescription) {
setStringValue(txn, "longDescription", longDescription);
}
/**
*
*/
public String getLongDescription() {
return getStringValue(longDescription);
}
/**
* Sets wheather or not this Song contains Video data
*/
public void setHasVideo(Transaction txn, boolean hasVideo) {
setBooleanValue(txn, "hasVideo", hasVideo);
}
/**
* Returns wheather or not this Song contains Video data
*/
public boolean hasVideo() {
return getBooleanValue(hasVideo);
}
/**
*
*/
private void addChunk(Chunk chunk) {
if (chunk != null) {
chunks.put(chunk.getName(), chunk);
}
}
protected Chunk getChunk(String name) {
return chunks.get(name);
}
/**
* Sets a new attachment and returns the old attachment. The attachment is
* an arbitrary Object but most likely a File, path, URI etc.
*/
public Object setAttachment(Object attachment) {
Object old = this.attachment;
this.attachment = attachment;
return old;
}
/**
* Returns the attachment.
*/
public Object getAttachment() {
return attachment;
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("Name: ").append(getName()).append("\n");
buffer.append("ID: ").append(getItemId()).append("\n");
buffer.append("Artist: ").append(getArtist()).append("\n");
buffer.append("Album: ").append(getAlbum()).append("\n");
buffer.append("Bitrate: ").append(getBitrate()).append("\n");
buffer.append("Genre: ").append(getGenre()).append("\n");
buffer.append("Comment: ").append(getComment()).append("\n");
return buffer.append("\n").toString();
}
@Override
public int hashCode() {
return (int) getItemId();
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Song)) {
return false;
}
return ((Song) o).getItemId() == getItemId();
}
protected void setBooleanValue(Transaction txn, String fieldName,
boolean value) {
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected void setUByteValue(Transaction txn, String fieldName, int value) {
UByteChunk.checkUByteRange(value);
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected void setSByteValue(Transaction txn, String fieldName, int value) {
SByteChunk.checkSByteRange(value);
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected void setUShortValue(Transaction txn, String fieldName, int value) {
UShortChunk.checkUShortRange(value);
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected void setSShortValue(Transaction txn, String fieldName, int value) {
SShortChunk.checkSShortRange(value);
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected void setUIntValue(Transaction txn, String fieldName, long value) {
UIntChunk.checkUIntRange(value);
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected void setSIntValue(Transaction txn, String fieldName, int value) {
// SIntChunk.checkSIntRange(value);
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected void setULongValue(Transaction txn, String fieldName, long value) {
// ULongChunk.checkULongRange(value);
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected void setSLongValue(Transaction txn, String fieldName, long value) {
// SLongChunk.checkSLongRange(value);
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected void setStringValue(Transaction txn, String fieldName,
String value) {
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected void setDateValue(Transaction txn, String fieldName, long value) {
DateChunk.checkDateRange(value);
if (txn != null) {
txn.addTxn(this, createNewTxn(fieldName, value));
} else {
setValue(fieldName, value);
}
}
protected boolean getBooleanValue(BooleanChunk chunk) {
return (chunk != null) ? chunk.getBooleanValue() : false;
}
protected int getSByteValue(SByteChunk chunk) {
return (chunk != null) ? chunk.getValue() : 0;
}
protected int getUByteValue(UByteChunk chunk) {
return (chunk != null) ? chunk.getValue() : 0;
}
protected int getUShortValue(UShortChunk chunk) {
return (chunk != null) ? chunk.getValue() : 0;
}
protected long getUIntValue(UIntChunk chunk) {
return (chunk != null) ? chunk.getUnsignedValue() : 0;
}
protected long getLongValue(LongChunk chunk) {
return (chunk != null) ? chunk.getValue() : 0;
}
protected long getDateValue(DateChunk chunk) {
return (chunk != null) ? chunk.getValue() : 0;
}
protected String getStringValue(StringChunk chunk) {
return (chunk != null) ? chunk.getValue() : null;
}
protected Txn createNewTxn(final String name, boolean value) {
return createNewTxn(name, boolean.class, new Boolean(value));
}
protected Txn createNewTxn(final String name, int value) {
return createNewTxn(name, int.class, new Integer(value));
}
protected Txn createNewTxn(final String name, long value) {
return createNewTxn(name, long.class, new Long(value));
}
protected Txn createNewTxn(final String name, String value) {
return createNewTxn(name, String.class, value);
}
protected Txn createNewTxn(final String fieldName,
final Class<?> valueClass, final Object value) {
Txn txn = new Txn() {
public void commit(Transaction txn) {
setValue(fieldName, valueClass, value);
}
};
return txn;
}
protected void setValue(String fieldName, boolean value) {
setValue(fieldName, boolean.class, new Boolean(value));
}
protected void setValue(String fieldName, int value) {
setValue(fieldName, int.class, new Integer(value));
}
protected void setValue(String fieldName, long value) {
setValue(fieldName, long.class, new Long(value));
}
protected void setValue(String fieldName, String value) {
setValue(fieldName, String.class, value);
}
protected void setValue(String fieldName, Class<?> valueClass, Object value) {
try {
Field field = Song.class.getDeclaredField(fieldName);
field.setAccessible(true);
Chunk chunk = (Chunk) field.get(this);
if (chunk == null) {
Constructor<?> con = field.getType().getConstructor(
new Class[] { valueClass });
chunk = (Chunk) con.newInstance(new Object[] { value });
field.set(this, chunk);
addChunk(chunk);
} else {
Method method = field.getType().getMethod("setValue",
new Class[] { valueClass });
method.invoke(chunk, new Object[] { value });
}
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
}
}
}