help me on //TODO parts * A Song is a sequence of Note objects. * The song can h
ID: 3886130 • Letter: H
Question
help me on //TODO parts
* A Song is a sequence of Note objects.
* The song can have a special "current element," which is specified and
* accessed through four methods that are available in the song class
* (start, getCurrent, advance and hasCurrent).
*
* @note
* (1) The capacity of a song can change after it's created, but
* the maximum capacity is limited by the amount of free memory on the
* machine. The constructor, insert, insertAll, clone,
* and catenation methods will result in an
* OutOfMemoryError when free memory is exhausted.
* <p>
* (2) A song's capacity cannot exceed the maximum integer 2,147,483,647
* (Integer.MAX_VALUE). Any attempt to create a larger capacity
* results in a failure due to an arithmetic overflow.
*
* NB: Neither of these conditions require any work for the implementors (students).
*
*
******************************************************************************/
public class Song implements Cloneable {
/** Static Constants */
private static final String DEFAULT_NAME = "Untitled";
private static final int DEFAULT_BPM = 60;
private static final int INITIAL_CAPACITY = 1;
public static final int MIN_BPM = 20, MAX_BPM = 1000;
/** Fields */
private String _name;
private int _bpm;
private Note[ ] _data;
private int _manyItems;
private int _currentIndex;
// Invariant of the Song class:
// 1. The name is not null.
// 2. The bpm is in the range [MIN_BPM,MAX_BPM]
// 3. The number of elements in the songs is in the instance variable
// manyItems.
// 4. For an empty song (with no elements), we do not care what is
// stored in any of data; for a non-empty song, the elements of the
// song are stored in data[0] through data[manyItems-1], and we
// don't care what's in the rest of data.
// 5. If there is a current element, then it lies in data[currentIndex];
// if there is no current element, then currentIndex equals manyItems.
private static boolean doReport = true; // change onluy in invariant tests
private boolean _report(String error) {
if (doReport) {
System.out.println("Invariant error: " + error);
}
return false;
}
private boolean _wellFormed() {
// Check the invariant.
// 1. name is never null
if (_name == null) return _report("name is null");
// 2. _bpm is in valid range: [MIN_BPM, MAX_BPM]
// TODO
// 3. data array is never null
// TODO
// 4. The data array has at least as many items in it as manyItems
// claims the song has
// TODO
// 5. currentIndex is never negative and never more than the number of
// items in the song.
// TODO
// If no problems discovered, return true
return true;
}
// This is only for testing the invariant. Do not change!
private Song(boolean testInvariant) { }
/**
* Initialize an empty song with name DEFAULT_NAME, bpm DEFAULT_BPM, and
* an initial capacity of INITIAL_CAPACITY. The {@link #insert(Note)} method works
* efficiently (without needing more memory) until this capacity is reached.
* @param - none
* @postcondition
* This song has the default name and BPM, is empty and has an initial capacity of INITIAL_CAPACITY
* @exception OutOfMemoryError
* Indicates insufficient memory for initial array.
**/
public Song( )
{
// TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of constructor";
}
/**
* Initialize an empty song with a specified name and bpm, an initial
* capacity of INITIAL_CAPACITY. The {@link #insert(Note)} method works
* efficiently (without needing more memory) until this capacity is reached.
* @param name
* the name of this song, must not be null
* @param bpm
* the beats per minute of this song, must be in the range [MIN_BPM,MAX_BPM]
* @postcondition
* This song is empty, has specified name and bpm, and has an initial
* capacity of INITIAL_CAPACITY.
* @throws IllegalArgumentException
* If the name is null, or the bpm is out of the legal range.
* @exception OutOfMemoryError
* Indicates insufficient memory for an array with this many elements.
* new Note[initialCapacity].
**/
public Song(String name, int bpm)
{
// TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of constructor";
}
/**
* Initialize an empty song with a specified initial capacity.
* The {@link #insert(Note)} method works
* efficiently (without needing more memory) until this capacity is reached.
* @param name
* the name of this song, must not be null
* @param bpm
* the beats per minute of this song, must be in the range [MIN_BPM,MAX_BPM]
* @param initialCapacity
* the initial capacity of this song, must not be negative
* @exception IllegalArgumentException
* Indicates that name, bpm or initialCapacity are invalid
* @exception OutOfMemoryError
* Indicates insufficient memory for an array with this many elements.
* new Note[initialCapacity].
**/
public Song(String name, int bpm, int initialCapacity)
{
// TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of constructor";
}
/**
* Gets the name of the song
* @return the name
*/
public String getName() {
assert _wellFormed() : "invariant failed at start of getName";
return _name;
}
/**
* Gets the beats per minute of the song.
* @return the bpm
*/
public int getBPM() {
assert _wellFormed() : "invariant failed at start of getBPM";
return _bpm;
}
/**
* Gets the total duration of the song by adding duration of all its notes.
* @return the total duration
*/
public double getDuration() {
assert _wellFormed() : "invariant failed at start of getDuration";
double result = 0;
// TODO
return result;
}
/**
* Sets the name of the song.
* @param newName the new name, must not be null
*/
public void setName(String newName) {
assert _wellFormed() : "invariant failed at start of setName";
// TODO
assert _wellFormed() : "invariant failed at end of setName";
}
/**
* Sets the beats per minute (BPM) of the song.
* @param newBPM the new bpm
* @throws IllegalArgumentException in the new BPM is not in the range [MIN_BPM,MAX_BPM]
*/
public void setBPM(int newBPM) {
assert _wellFormed() : "invariant failed at start of setBPM";
// TODO
assert _wellFormed() : "invariant failed at end of setBPM";
}
/**
* Stretches the song by the given factor, lengthening or shortening its duration.
* If there's a problem with one of the notes, this Song may be left
* partially stretched.
* @param factor the factor to multiply each note's duration by
* @throws IllegalArgumentException if song is transposed where a note's duration
* is beyond the valid bounds
*/
public void stretch(double factor) {
assert _wellFormed() : "invariant failed at start of stretch";
// TODO stretch each note in the song
assert _wellFormed() : "invariant failed at end of stretch";
}
/**
* Transposes the song by the given interval, raising or lowering its pitch.
* If there's a problem with transposing one of the notes, this Song may be left
* partially transposed.
* @param interval the interval to transpose each note in the song
* @throws IllegalArgumentException if song is transposed where a note is beyond the bounds
* of valid MIDI pitch values [0,127]
*/
public void transpose(int interval) {
assert _wellFormed() : "invariant failed at start of transpose";
// TODO transpose each note in the song
assert _wellFormed() : "invariant failed at end of transpose";
}
/**
* Add a new element to this song, before the current element (if any).
* If the new element would take this song beyond its current capacity,
* then the capacity is increased before adding the new element.
* @param element
* the new element that is being added
* @postcondition
* A new copy of the element has been added to this song. If there was
* a current element, then the new element is placed before the current
* element. If there was no current element, then the new element is placed
* at the end of the song. In all cases, the new element becomes the
* new current element of this song.
* @exception OutOfMemoryError
* Indicates insufficient memory for increasing the song's capacity.
**/
public void insert(Note element)
{
assert _wellFormed() : "invariant failed at start of insert";
// TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of insert";
}
/**
* Move forward, so that the current element is now the next element in
* this song.
* @param - none
* @precondition
* hasCurrent() returns true.
* @postcondition
* If the current element was already the end element of this song
* (with nothing after it), then there is no longer any current element.
* Otherwise, the new element is the element immediately after the
* original current element.
* @exception IllegalStateException
* Indicates that there is no current element, so
* advance may not be called.
**/
public void advance( )
{
assert _wellFormed() : "invariant failed at start of advance";
// TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of advance";
}
/**
* Generate a copy of this song.
* @param - none
* @return
* The return value is a copy of this song. Subsequent changes to the
* copy will not affect the original, nor vice versa.
* @exception OutOfMemoryError
* Indicates insufficient memory for creating the clone.
**/
public Song clone( ) {
assert _wellFormed() : "invariant failed at start of clone";
Song answer;
try
{
answer = (Song) super.clone( );
}
catch (CloneNotSupportedException e)
{ // This exception should not occur. But if it does, it would probably
// indicate a programming error that made super.clone unavailable.
// The most common error would be forgetting the "Implements Cloneable"
// clause at the start of this class.
throw new RuntimeException
("This class does not implement Cloneable");
}
// all that is needed is to clone the data array.
// (Exercise: Why is this needed?)
answer._data = _data.clone( );
assert _wellFormed() : "invariant failed at end of clone";
assert answer._wellFormed() : "invariant on answer failed at end of clone";
return answer;
}
/**
* Place the contents of another song (which may be the
* same song as this!) into this song before the current element.
* @param addend
* a song whose contents will be placed into this song
* @precondition
* The parameter, addend, is not null.
* @postcondition
* The elements from addend have been placed into
* this song. The current element of this song is now
* the first element inserted (if any). If the added song
* is empty, this song and the current element (if any) are
* unchanged.
* @exception NullPointerException
* Indicates that addend is null.
* @exception OutOfMemoryError
* Indicates insufficient memory to increase the size of this song.
**/
public void insertAll(Song addend)
{
assert _wellFormed() : "invariant failed at start of insertAll";
// TODO: Implemented by student.
// Watch out for the this==addend case!
// (It is possible to write code that works for this case AND
// the normal case, but you have to be very careful.)
assert _wellFormed() : "invariant failed at end of insertAll";
assert addend._wellFormed() : "invariant of addend broken in insertAll";
}
/**
* Create a new song that contains all the elements from one song
* followed by another. The new BPM is the average of the two songs,
* and the name is the concatenation of the two names separated by " and "
* @param s1
* the first of two songs
* @param s2
* the second of two songs
* @precondition
* Neither s1 nor s2 is null.
* @return
* a new song that has the elements of s1 followed by the
* elements of s2 (with no current element).
* @exception NullPointerException.
* Indicates that one of the arguments is null.
* @exception OutOfMemoryError
* Indicates insufficient memory for the new song.
**/
public static Song catenation(Song s1, Song s2)
{
assert s1._wellFormed() : "invariant of s1 failed at start of catenation";
assert s2._wellFormed() : "invariant of s2 failed at start of catenation";
Song res;
// TODO: Implemented by student.
assert s1._wellFormed() : "invariant of s1 failed at end of catenation";
assert s2._wellFormed() : "invariant of s2 failed at end of catenation";
assert res._wellFormed() : "invariant of res failed at end of catenation";
return res;
}
/**
* Change the current capacity of this song as needed so that
* the capacity is at least as big as the parameter.
* This code must work correctly and efficiently if the minimum
* capacity is (1) smaller or equal to the current capacity (do nothing)
* (2) at most double the current capacity (double the capacity)
* or (3) more than double the current capacity (new capacity is the
* minimum passed).
* @param minimumCapacity
* the new capacity for this song
* @postcondition
* This song's capacity has been changed to at least minimumCapacity.
* If the capacity was already at or greater than minimumCapacity,
* then the capacity is left unchanged.
* @exception OutOfMemoryError
* Indicates insufficient memory for: new array of minimumCapacity elements.
**/
private void ensureCapacity(int minimumCapacity)
{
// TODO: Implemented by student.
// NB: do not check invariant
}
/**
* Accessor method to get the current element of this song.
* @param - none
* @precondition
* hasCurrent() returns true.
* @return
* the current element of this song
* @exception IllegalStateException
* Indicates that there is no current element, so
* getCurrent may not be called.
**/
public Note getCurrent( )
{
assert _wellFormed() : "invariant failed at start of getCurrent";
// TODO: Implemented by student.
// Don't change "this"!
}
/**
* Accessor method to determine whether this song has a specified
* current element that can be retrieved with the
* getCurrent method.
* @param - none
* @return
* true (there is a current element) or false (there is no current element at the moment)
**/
public boolean hasCurrent( )
{
assert _wellFormed() : "invariant failed at start of hasCurrent";
// TODO: Implemented by student.
}
/**
* Remove the current element from this song.
* @param - none
* @precondition
* hasCurrent() returns true.
* @postcondition
* The current element has been removed from this song, and the
* following element (if there is one) is now the new current element.
* If there was no following element, then there is now no current
* element.
* @exception IllegalStateException
* Indicates that there is no current element, so
* removeCurrent may not be called.
**/
public void removeCurrent( )
{
assert _wellFormed() : "invariant failed at start of removeCurrent";
// TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of removeCurrent";
}
/**
* Determine the number of elements in this song.
* @param - none
* @return
* the number of elements in this song
**/
public int size( )
{
assert _wellFormed() : "invariant failed at start of size";
// TODO: Implemented by student.
}
/**
* Set the current element at the front of this song.
* @param - none
* @postcondition
* The front element of this song is now the current element (but
* if this song has no elements at all, then there is no current
* element).
**/
public void start( )
{
assert _wellFormed() : "invariant failed at start of start";
// TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of start";
}
// don't change this nested class:
public static class TestInvariantChecker extends TestCase {
Song hs = new Song(false);
protected void setUp() {
hs = new Song(false);
hs._name = "";
hs._bpm = MIN_BPM;
Song.doReport = false;
}
public void test0() {
assertFalse(hs._wellFormed());
}
public void test1() {
hs._data = new Note[0];
assertTrue(hs._wellFormed());
hs._name = null;
assertFalse(hs._wellFormed());
}
public void test2() {
hs._data = new Note[1];
assertTrue(hs._wellFormed());
hs._bpm = MIN_BPM-1;
assertFalse(hs._wellFormed());
hs._bpm = MAX_BPM+1;
assertFalse(hs._wellFormed());
hs._bpm = MAX_BPM;
assertTrue(hs._wellFormed());
}
public void test6() {
hs._data = new Note[3];
hs._manyItems = -2;
assertFalse(hs._wellFormed());
hs._manyItems = -1;
assertFalse(hs._wellFormed());
hs._manyItems = 0;
assertTrue(hs._wellFormed());
}
public void test7() {
hs._data = new Note[3];
hs._manyItems = 4;
assertFalse(hs._wellFormed());
hs._manyItems = 3;
assertTrue(hs._wellFormed());
}
public void test8() {
hs._data = new Note[3];
hs._manyItems = 2;
hs._currentIndex = -1;
assertFalse(hs._wellFormed());
hs._currentIndex = 3;
assertFalse(hs._wellFormed());
hs._currentIndex = 2;
assertTrue(hs._wellFormed());
}
}
}
Explanation / Answer
import junit.framework.TestCase;
/*help me on //TODO parts
A Song is a sequence of Note objects.
* The song can have a special "current element," which is specified and
* accessed through four methods that are available in the song class
* (start, getCurrent, advance and hasCurrent).
*
* @note
* (1) The capacity of a song can change after it's created, but
* the maximum capacity is limited by the amount of free memory on the
* machine. The constructor, insert, insertAll, clone,
* and catenation methods will result in an
* OutOfMemoryError when free memory is exhausted.
* <p>
* (2) A song's capacity cannot exceed the maximum integer 2,147,483,647
* (Integer.MAX_VALUE). Any attempt to create a larger capacity
* results in a failure due to an arithmetic overflow.
*
* NB: Neither of these conditions require any work for the implementors (students).
*
*
******************************************************************************/
public class Song implements Cloneable {
/** Static Constants */
private static final String DEFAULT_NAME = "Untitled";
private static final int DEFAULT_BPM = 60;
private static final int INITIAL_CAPACITY = 1;
public static final int MIN_BPM = 20, MAX_BPM = 1000;
/** Fields */
private String _name;
private int _bpm;
private Note[ ] _data;
private int _manyItems;
private int _currentIndex;
//Invariant of the Song class:
// 1. The name is not null.
// 2. The bpm is in the range [MIN_BPM,MAX_BPM]
// 3. The number of elements in the songs is in the instance variable
// manyItems.
// 4. For an empty song (with no elements), we do not care what is
// stored in any of data; for a non-empty song, the elements of the
// song are stored in data[0] through data[manyItems-1], and we
// don't care what's in the rest of data.
// 5. If there is a current element, then it lies in data[currentIndex];
// if there is no current element, then currentIndex equals manyItems.
private static boolean doReport = true; // change onluy in invariant tests
private boolean _report(String error) {
if (doReport) {
System.out.println("Invariant error: " + error);
}
return false;
}
private boolean _wellFormed() {
//Check the invariant.
//1. name is never null
if (_name == null) return _report("name is null");
//2. _bpm is in valid range: [MIN_BPM, MAX_BPM]
//TODO
if(_bpm<MIN_BPM || _bpm >MAX_BPM) return _report("_bpm is in invalid range");
//3. data array is never null
//TODO
if(_data== null) return _report("data array is null");
//4. The data array has at least as many items in it as manyItems
// claims the song has
//TODO
if(_data.length<_manyItems) return _report("The data array doesn't has at least as many items in it as manyItems");
//5. currentIndex is never negative and never more than the number of
// items in the song.
//TODO
if((_currentIndex<0 )&& (_currentIndex > _manyItems-1) )return _report("currentIndex is never negative and never more than the number of items in the song");
//If no problems discovered, return true
return true;
}
//This is only for testing the invariant. Do not change!
private Song(boolean testInvariant) { }
/**
* Initialize an empty song with name DEFAULT_NAME, bpm DEFAULT_BPM, and
* an initial capacity of INITIAL_CAPACITY. The {@link #insert(Note)} method works
* efficiently (without needing more memory) until this capacity is reached.
* @param - none
* @postcondition
* This song has the default name and BPM, is empty and has an initial capacity of INITIAL_CAPACITY
* @exception OutOfMemoryError
* Indicates insufficient memory for initial array.
**/
public Song( )
{
//TODO: Implemented by student.
_name=DEFAULT_NAME;
_bpm=DEFAULT_BPM;
_data=new Note[INITIAL_CAPACITY];
assert _wellFormed() : "invariant failed at end of constructor";
}
/**
* Initialize an empty song with a specified name and bpm, an initial
* capacity of INITIAL_CAPACITY. The {@link #insert(Note)} method works
* efficiently (without needing more memory) until this capacity is reached.
* @param name
* the name of this song, must not be null
* @param bpm
* the beats per minute of this song, must be in the range [MIN_BPM,MAX_BPM]
* @postcondition
* This song is empty, has specified name and bpm, and has an initial
* capacity of INITIAL_CAPACITY.
* @throws IllegalArgumentException
* If the name is null, or the bpm is out of the legal range.
* @exception OutOfMemoryError
* Indicates insufficient memory for an array with this many elements.
* new Note[initialCapacity].
**/
public Song(String name, int bpm)
{
//TODO: Implemented by student.
if(name==null)
throw new IllegalArgumentException("name is null");
if(_bpm<MIN_BPM || _bpm >MAX_BPM)
throw new IllegalArgumentException("bpm is in invalid range");
_name=name;
_bpm=bpm;
_data=new Note[INITIAL_CAPACITY];
assert _wellFormed() : "invariant failed at end of constructor";
}
/**
* Initialize an empty song with a specified initial capacity.
* The {@link #insert(Note)} method works
* efficiently (without needing more memory) until this capacity is reached.
* @param name
* the name of this song, must not be null
* @param bpm
* the beats per minute of this song, must be in the range [MIN_BPM,MAX_BPM]
* @param initialCapacity
* the initial capacity of this song, must not be negative
* @exception IllegalArgumentException
* Indicates that name, bpm or initialCapacity are invalid
* @exception OutOfMemoryError
* Indicates insufficient memory for an array with this many elements.
* new Note[initialCapacity].
**/
public Song(String name, int bpm, int initialCapacity)
{
//TODO: Implemented by student.
if(name==null)
throw new IllegalArgumentException("name is null");
if(_bpm<MIN_BPM || _bpm >MAX_BPM)
throw new IllegalArgumentException("bpm is in invalid range");
if(initialCapacity<0)
throw new IllegalArgumentException("initialCapacity is null");
_name=name;
_bpm=bpm;
_data=new Note{initialCapacity];
assert _wellFormed() : "invariant failed at end of constructor";
}
/**
* Gets the name of the song
* @return the name
*/
public String getName() {
assert _wellFormed() : "invariant failed at start of getName";
return _name;
}
/**
* Gets the beats per minute of the song.
* @return the bpm
*/
public int getBPM() {
assert _wellFormed() : "invariant failed at start of getBPM";
return _bpm;
}
/**
* Gets the total duration of the song by adding duration of all its notes.
* @return the total duration
*/
public double getDuration() {
assert _wellFormed() : "invariant failed at start of getDuration";
double result = 0;
//TODO
for(int i=0;i<Note.length;i++){
result+=Note[i].getDuration();
}
return result;
}
/**
* Sets the name of the song.
* @param newName the new name, must not be null
*/
public void setName(String newName) {
assert _wellFormed() : "invariant failed at start of setName";
//TODO
_name=newName;
assert _wellFormed() : "invariant failed at end of setName";
}
/**
* Sets the beats per minute (BPM) of the song.
* @param newBPM the new bpm
* @throws IllegalArgumentException in the new BPM is not in the range [MIN_BPM,MAX_BPM]
*/
public void setBPM(int newBPM) {
assert _wellFormed() : "invariant failed at start of setBPM";
//TODO
if(_bpm<MIN_BPM || _bpm >MAX_BPM){
throw new IllegalArgumentException("new BPM is not in the range ["+MIN_BPM+","+MAX_BPM+"]");
}
_bpm=newBPM;
assert _wellFormed() : "invariant failed at end of setBPM";
}
/**
* Stretches the song by the given factor, lengthening or shortening its duration.
* If there's a problem with one of the notes, this Song may be left
* partially stretched.
* @param factor the factor to multiply each note's duration by
* @throws IllegalArgumentException if song is transposed where a note's duration
* is beyond the valid bounds
*/
public void stretch(double factor) {
assert _wellFormed() : "invariant failed at start of stretch";
//TODO stretch each note in the song
assert _wellFormed() : "invariant failed at end of stretch";
}
/**
* Transposes the song by the given interval, raising or lowering its pitch.
* If there's a problem with transposing one of the notes, this Song may be left
* partially transposed.
* @param interval the interval to transpose each note in the song
* @throws IllegalArgumentException if song is transposed where a note is beyond the bounds
* of valid MIDI pitch values [0,127]
*/
public void transpose(int interval) {
assert _wellFormed() : "invariant failed at start of transpose";
//TODO transpose each note in the song
assert _wellFormed() : "invariant failed at end of transpose";
}
/**
* Add a new element to this song, before the current element (if any).
* If the new element would take this song beyond its current capacity,
* then the capacity is increased before adding the new element.
* @param element
* the new element that is being added
* @postcondition
* A new copy of the element has been added to this song. If there was
* a current element, then the new element is placed before the current
* element. If there was no current element, then the new element is placed
* at the end of the song. In all cases, the new element becomes the
* new current element of this song.
* @exception OutOfMemoryError
* Indicates insufficient memory for increasing the song's capacity.
**/
public void insert(Note element)
{
assert _wellFormed() : "invariant failed at start of insert";
//TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of insert";
}
/**
* Move forward, so that the current element is now the next element in
* this song.
* @param - none
* @precondition
* hasCurrent() returns true.
* @postcondition
* If the current element was already the end element of this song
* (with nothing after it), then there is no longer any current element.
* Otherwise, the new element is the element immediately after the
* original current element.
* @exception IllegalStateException
* Indicates that there is no current element, so
* advance may not be called.
**/
public void advance( )
{
assert _wellFormed() : "invariant failed at start of advance";
//TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of advance";
}
/**
* Generate a copy of this song.
* @param - none
* @return
* The return value is a copy of this song. Subsequent changes to the
* copy will not affect the original, nor vice versa.
* @exception OutOfMemoryError
* Indicates insufficient memory for creating the clone.
**/
public Song clone( ) {
assert _wellFormed() : "invariant failed at start of clone";
Song answer;
try
{
answer = (Song) super.clone( );
}
catch (CloneNotSupportedException e)
{ // This exception should not occur. But if it does, it would probably
//indicate a programming error that made super.clone unavailable.
//The most common error would be forgetting the "Implements Cloneable"
//clause at the start of this class.
throw new RuntimeException
("This class does not implement Cloneable");
}
//all that is needed is to clone the data array.
//(Exercise: Why is this needed?)
answer._data = _data.clone( );
assert _wellFormed() : "invariant failed at end of clone";
assert answer._wellFormed() : "invariant on answer failed at end of clone";
return answer;
}
/**
* Place the contents of another song (which may be the
* same song as this!) into this song before the current element.
* @param addend
* a song whose contents will be placed into this song
* @precondition
* The parameter, addend, is not null.
* @postcondition
* The elements from addend have been placed into
* this song. The current element of this song is now
* the first element inserted (if any). If the added song
* is empty, this song and the current element (if any) are
* unchanged.
* @exception NullPointerException
* Indicates that addend is null.
* @exception OutOfMemoryError
* Indicates insufficient memory to increase the size of this song.
**/
public void insertAll(Song addend)
{
assert _wellFormed() : "invariant failed at start of insertAll";
//TODO: Implemented by student.
//Watch out for the this==addend case!
//(It is possible to write code that works for this case AND
//the normal case, but you have to be very careful.)
assert _wellFormed() : "invariant failed at end of insertAll";
assert addend._wellFormed() : "invariant of addend broken in insertAll";
}
/**
* Create a new song that contains all the elements from one song
* followed by another. The new BPM is the average of the two songs,
* and the name is the concatenation of the two names separated by " and "
* @param s1
* the first of two songs
* @param s2
* the second of two songs
* @precondition
* Neither s1 nor s2 is null.
* @return
* a new song that has the elements of s1 followed by the
* elements of s2 (with no current element).
* @exception NullPointerException.
* Indicates that one of the arguments is null.
* @exception OutOfMemoryError
* Indicates insufficient memory for the new song.
**/
public static Song catenation(Song s1, Song s2)
{
assert s1._wellFormed() : "invariant of s1 failed at start of catenation";
assert s2._wellFormed() : "invariant of s2 failed at start of catenation";
Song res;
//TODO: Implemented by student.
assert s1._wellFormed() : "invariant of s1 failed at end of catenation";
assert s2._wellFormed() : "invariant of s2 failed at end of catenation";
assert res._wellFormed() : "invariant of res failed at end of catenation";
return res;
}
/**
* Change the current capacity of this song as needed so that
* the capacity is at least as big as the parameter.
* This code must work correctly and efficiently if the minimum
* capacity is (1) smaller or equal to the current capacity (do nothing)
* (2) at most double the current capacity (double the capacity)
* or (3) more than double the current capacity (new capacity is the
* minimum passed).
* @param minimumCapacity
* the new capacity for this song
* @postcondition
* This song's capacity has been changed to at least minimumCapacity.
* If the capacity was already at or greater than minimumCapacity,
* then the capacity is left unchanged.
* @exception OutOfMemoryError
* Indicates insufficient memory for: new array of minimumCapacity elements.
**/
private void ensureCapacity(int minimumCapacity)
{
//TODO: Implemented by student.
//NB: do not check invariant
}
/**
* Accessor method to get the current element of this song.
* @param - none
* @precondition
* hasCurrent() returns true.
* @return
* the current element of this song
* @exception IllegalStateException
* Indicates that there is no current element, so
* getCurrent may not be called.
**/
public Note getCurrent( )
{
assert _wellFormed() : "invariant failed at start of getCurrent";
//TODO: Implemented by student.
//Don't change "this"!
}
/**
* Accessor method to determine whether this song has a specified
* current element that can be retrieved with the
* getCurrent method.
* @param - none
* @return
* true (there is a current element) or false (there is no current element at the moment)
**/
public boolean hasCurrent( )
{
assert _wellFormed() : "invariant failed at start of hasCurrent";
//TODO: Implemented by student.
}
/**
* Remove the current element from this song.
* @param - none
* @precondition
* hasCurrent() returns true.
* @postcondition
* The current element has been removed from this song, and the
* following element (if there is one) is now the new current element.
* If there was no following element, then there is now no current
* element.
* @exception IllegalStateException
* Indicates that there is no current element, so
* removeCurrent may not be called.
**/
public void removeCurrent( )
{
assert _wellFormed() : "invariant failed at start of removeCurrent";
//TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of removeCurrent";
}
/**
* Determine the number of elements in this song.
* @param - none
* @return
* the number of elements in this song
**/
public int size( )
{
assert _wellFormed() : "invariant failed at start of size";
return _data.length;
//TODO: Implemented by student.
}
/**
* Set the current element at the front of this song.
* @param - none
* @postcondition
* The front element of this song is now the current element (but
* if this song has no elements at all, then there is no current
* element).
**/
public void start( )
{
assert _wellFormed() : "invariant failed at start of start";
//TODO: Implemented by student.
assert _wellFormed() : "invariant failed at end of start";
}
//don't change this nested class:
public static class TestInvariantChecker extends TestCase {
Song hs = new Song(false);
protected void setUp() {
hs = new Song(false);
hs._name = "";
hs._bpm = MIN_BPM;
Song.doReport = false;
}
public void test0() {
assertFalse(hs._wellFormed());
}
public void test1() {
hs._data = new Note[0];
assertTrue(hs._wellFormed());
hs._name = null;
assertFalse(hs._wellFormed());
}
public void test2() {
hs._data = new Note[1];
assertTrue(hs._wellFormed());
hs._bpm = MIN_BPM-1;
assertFalse(hs._wellFormed());
hs._bpm = MAX_BPM+1;
assertFalse(hs._wellFormed());
hs._bpm = MAX_BPM;
assertTrue(hs._wellFormed());
}
public void test6() {
hs._data = new Note[3];
hs._manyItems = -2;
assertFalse(hs._wellFormed());
hs._manyItems = -1;
assertFalse(hs._wellFormed());
hs._manyItems = 0;
assertTrue(hs._wellFormed());
}
public void test7() {
hs._data = new Note[3];
hs._manyItems = 4;
assertFalse(hs._wellFormed());
hs._manyItems = 3;
assertTrue(hs._wellFormed());
}
public void test8() {
hs._data = new Note[3];
hs._manyItems = 2;
hs._currentIndex = -1;
assertFalse(hs._wellFormed());
hs._currentIndex = 3;
assertFalse(hs._wellFormed());
hs._currentIndex = 2;
assertTrue(hs._wellFormed());
}
}
}