package net.obnoxint.mcdev.util;
import java.io.Serializable;
import org.bukkit.Instrument;
import org.bukkit.Location;
import org.bukkit.Note;
import org.bukkit.Note.Tone;
import org.bukkit.entity.Player;
/**
* A serializable and immutable wrapper-class, combining org.bukkit.Instrument and org.bukkit.Note.<br>
*
* @author obnoxint
*/
public class SerializableNote implements Serializable {
private static final long serialVersionUID = 6300854456299424547L;
protected static final String DELIMITER = "-";
protected static final String SHARP = "#";
/**
* Gets a SerializableNote from a pair of bytes.<br>
* Also checks if the pair results in a legal SerializableNote whose corresponding Instrument-Note-pair can be used by CraftBukkit without causing an
* IllegalArgumentException.
*
* @param instrument the type of the instrument.
* @param note the id of the note.
* @return the SerializableNote.
*/
public static SerializableNote fromRaw(final byte instrument, final byte note) {
final SerializableNote r = new SerializableNote(instrument, note);
return r.validate() ? r : null;
}
/**
* Gets a SerializableNote from an array of bytes.<br>
* The general contract of this method is that the method equals() in the following example returns true:<br>
* <code>
* SerializableNote sn = new SerializableNote(instrument, note)<br>
* return sn.equals(SerializableNote.fromRaw(sn.toRaw()));
* </code>
*
* @param data a byte-array with the length of 2.
* @return the SerializableNote or null if the given data would not lead to a valid SerializableNote (see fromRaw(byte, byte)).
* @throws IllegalArgumentException if data is null or has not the length of 2.
*/
public static SerializableNote fromRaw(final byte[] data) throws IllegalArgumentException {
if (data != null && data.length == 2) {
return fromRaw(data[0], data[1]);
}
throw new IllegalArgumentException();
}
/**
* Gets a SerializableNote from a String.<br>
* The general contract of this method is that the method equals() in the following example returns true:<br>
* <code>
* SerializableNote sn = new SerializableNote(instrument, note)<br>
* return sn.equals(SerializableNote.fromString(sn.toString()));
* </code>
*
* @param string the String.
* @return the SerializableNote.
*/
public static SerializableNote fromString(final String string) {
final SerializableNote r = null;
if (string != null) {
try {
final String split[] = string.trim().split(DELIMITER);
if (split.length == 2) {
split[0] = split[0].trim();
split[1] = split[1].trim();
if (!split[0].isEmpty() && !split[1].isEmpty()) {
final Instrument instrument = Instrument.valueOf(split[0].toUpperCase());
if (instrument != null) {
final boolean sharped = split[1].startsWith(SHARP);
if (sharped) {
split[1] = split[1].substring(1);
}
if (split[1].length() == 2) {
final Tone tone = Tone.valueOf(split[1].substring(0, 1).toUpperCase());
final int octave = Integer.valueOf(split[1].substring(1));
if (tone != null) {
return new SerializableNote(instrument, new Note(octave, tone, sharped));
}
}
}
}
}
} catch (final Exception e) {}
}
return r;
}
private final byte instrument;
private final byte note;
/**
* Constructs a new SerializableNote.
*
* @param instrument the Instrument.
* @param note the Note.
*/
public SerializableNote(final Instrument instrument, final Note note) {
if (instrument == null || note == null) {
throw new IllegalArgumentException("Null reference not permitted.");
}
this.instrument = instrument.getType();
this.note = note.getId();
}
private SerializableNote(final byte instrument, final byte note) {
this.instrument = instrument;
this.note = note;
}
@Override
public boolean equals(final Object obj) {
if (obj != null) {
if (obj instanceof SerializableNote) {
final SerializableNote o = (SerializableNote) obj;
return (o.instrument == instrument) && (o.note == note);
} else if (obj instanceof byte[]) {
final byte[] o = (byte[]) obj;
return (o.length == 2) && (o[0] == instrument) && (o[1] == note);
} else if (obj instanceof Instrument) {
return ((Instrument) obj).getType() == instrument;
} else if (obj instanceof Note) {
return ((Note) obj).getId() == note;
}
}
return false;
}
/**
* Gets the wrapped org.bukkit.Instrument.
*
* @return the Instrument.
*/
public Instrument getInstrument() {
return Instrument.getByType(instrument);
}
/**
* Gets the wrapped org.bukkit.Note.
*
* @return the Note.
*/
public Note getNote() {
return new Note(note);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + instrument;
result = prime * result + note;
return result;
}
/**
* Plays this SerializableNote to the given player at the players location current location.
*
* @param player the Player.
*/
public void play(final Player player) {
play(player, player.getLocation());
}
/**
* Plays this SerializableNote to the given player at the given location.
*
* @param player the Player.
* @param location the Location.
*/
public void play(final Player player, final Location location) {
player.playNote(location, instrument, note);
}
/**
* Gets a byte array with the length of 2 representing this SerializableNote.
*
* @return a byte array with the length of 2. The first byte represents the type of the Instrument, the second byte represents the id of the Note.
*/
public byte[] toRaw() {
final byte[] r = new byte[2];
r[0] = instrument;
r[1] = note;
return r;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
try {
final String instrument = getInstrument().name();
final boolean sharp = getNote().isSharped();
final String tone = getNote().getTone().name();
final int octave = getNote().getOctave();
sb.append(instrument).append(DELIMITER);
if (sharp) {
sb.append(SHARP);
}
sb.append(tone).append(octave);
} catch (final Exception e) {}
return sb.toString();
}
private boolean validate() {
return fromString(toString()) != null;
}
}