Program02/AVLDriver.java
Program02/AVLDriver.java
import java.util.ArrayList;
import java.util.Iterator;
public class AVLDriver
{
public static void main(String[] args)
{
AVLTree avlTree = new AVLTree();
FileIO file = new FileIO("cds.txt", ",");
try
{
while(file.EOF()==false)
{
String artist = file.readLine();
if(artist==null)
{
break;
}
String title = file.readLine();
int year = Integer.parseInt(file.readLine());
int rating = Integer.parseInt(file.readLine());
int tracks = Integer.parseInt(file.readLine());
CD cd = new CD(title, artist, year, rating, tracks);
for(int i=0;i {
Iterator iter = file.getTokens();
String length = iter.next();
String songTitle = iter.next();
cd.addSong(songTitle, length);
}
avlTree.insert(cd);
}
}
catch (FileIOException e) {
System.out.println(e.getMessage());
}
catch (TreeException e) {
System.out.println(e.getMessage());
}
catch (Exception e) {
System.out.println(e.getMessage());
}
WorstCDs worstCDsCommand = new WorstCDs();
avlTree.execute(worstCDsCommand);
ArrayList worstCDs = worstCDsCommand.getWorstCDs();
if(worstCDs.size()==0)
{
System.out.println("No CDs found");
}
else
{
System.out.println("CD(s) with lowest rating of "+worstCDs.get(0).getRating()+" are:");
for(int i = 0;i {
System.out.println( (i+1) + ". " +worstCDs.get(i).getKey());
}
}
System.out.println();
LongestSong longestSongCommand = new LongestSong();
avlTree.execute(longestSongCommand);
Song longestSong = longestSongCommand.getLongestSong();
if(longestSong==null)
{
System.out.println("No CDs/songs found");
}
else
{
System.out.println("The longest song is: "+longestSong.getTitle()+", with length " + (longestSong.getLength()/60)+":"+(longestSong.getLength()%60));
}
}
}
Program02/AVLTree.java
Program02/AVLTree.java
import java.util.Iterator;
//should consider not extending BST as a lot of knowledge about parent class implementation
//is necessary to write this class
public final class AVLTree extends BinarySearchTree implements Execute
{
private boolean avlFlag;
public AVLTree()
{
super();
}
public void insert(KeyedItem item) throws TreeException
{
super.insert(item);
avlFlag = false;
assert isBalanced() : "tree is not balanced after insertion of key: " + item.getKey();
}
public void delete(Comparable sk) throws TreeException
{
super.delete(sk);
avlFlag = false;
assert isBalanced() : "tree is not balanced after deletion of key: " + sk;
}
//overriding these protected methods requires knowledge of the parent class' implementation
protected TreeNode createNode(KeyedItem item)
{
TreeNode tNode = new AVLTreeNode(item);
avlFlag = true;
return tNode;
}
protected TreeNode insertLeft(TreeNode tNode, KeyedItem item)
{
tNode = super.insertLeft(tNode, item);
AVLTreeNode avltn = (AVLTreeNode) tNode;
if (avlFlag)
{
avltn = avlFixAddLeft(avltn);
}
return avltn;
}
protected TreeNode insertRight(TreeNode tNode, KeyedItem item)
{
tNode = super.insertRight(tNode, item);
AVLTreeNode avltn = (AVLTreeNode) tNode;
if (avlFlag)
{
avltn = avlFixAddRight(avltn);
}
return avltn;
}
//sets balance factors and calls the inherited rotate right method
private AVLTreeNode singleRight(AVLTreeNode tNode)
{
AVLTreeNode left = tNode.getLeft();
tNode.setBalanceFactor(AVL.BALANCED);
left.setBalanceFactor(AVL.BALANCED);
tNode = (AVLTreeNode) rotateRight(tNode);
//System.out.println("SR");
return tNode;
}
private AVLTreeNode singleLeft(AVLTreeNode tNode)
{
AVLTreeNode right = tNode.getRight();
tNode.setBalanceFactor(AVL.BALANCED);
right.setBalanceFactor(AVL.BALANCED);
tNode = (AVLTreeNode) rotateLeft(tNode);
//System.out.println("SL");
return tNode;
}
private AVLTreeNode doubleLeftRight(AVLTreeNode tNode)
{
AVLTreeNode left = tNode.getLeft();
AVLTreeNode leftRight = left.getRight();
//next line determines the rotation
AVL bF = leftRight.getBalanceFactor();
leftRight.setBalanceFactor(AVL.BALANCED);
tNode.setBalanceFactor(AVL.BALANCED);
left.setBalanceFactor(AVL.BALANCED);
if (bF == AVL.RIGHT)
{
//tNode.setBalanceFactor(AVL.BALANCED);
left.setBalanceFactor(AVL.LEFT);
}
else if (bF == AVL.LEFT)
{
tNode.setBalanceFactor(AVL.RIGHT);
//left.setBalanceFactor(AVL.BALANCED);
}
//do the rotation
AVLTreeNode temp = (AVLTreeNode) rotateLeft(left);
tNode.setLeft(temp);
tNode = (AVLTreeNode) rotateRight(tNode);
//System.out.println("DLR");
return tNode;
}
private AVLTreeNode doubleRightLeft(AVLTreeNode tNode)
{
AVLTreeNode right = tNode.getRight();
AVLTreeNode rightLeft = right.getLeft();
//next line determines the rotation
AVL bF = rightLeft.getBalanceFactor();
rightLeft.setBalanceFactor(AVL.BALANCED);
tNode.setBalanceFactor(AVL.BALANCED);
right.setBalanceFactor(AVL.BALANCED);
if (bF == AVL.RIGHT)
{
tNode.setBalanceFactor(AVL.LEFT);
//right.setBalanceFactor(AVL.BALANCED);
}
else if (bF == AVL.LEFT)
{
//tNode.setBalanceFactor(AVL.BALANCED);
right.setBalanceFactor(AVL.RIGHT);
}
AVLTreeNode temp = (AVLTreeNode) rotateRight(right);
tNode.setRight(temp);
tNode = (AVLTreeNode) rotateLeft(tNode);
//System.out.println("DRL");
return tNode;
}
private AVLTreeNode avlFixAddLeft(AVLTreeNode tNode)
{
//b, l, and lu are the only possible balance factors
tNode.insertLeft();
AVL factor = tNode.getBalanceFactor();
if (factor == AVL.BALANCED)
{
avlFlag = false; //no more to do this time around
return tNode;
}
else if (factor == AVL.LEFT)
{
return tNode; //no rotation necessary at this node, but need to keep checking upwards
}
//the balance factor must be lu
AVLTreeNode left = tNode.getLeft();
if (left.getBalanceFactor() == AVL.RIGHT)
{
tNode = doubleLeftRight(tNode);
}
else
{
tNode = singleRight(tNode);
}
avlFlag = false; //basically, stop checking (return the replacement node for this position)
return tNode;
}
private AVLTreeNode avlFixAddRight(AVLTreeNode tNode)
{
tNode.insertRight();
AVL factor = tNode.getBalanceFactor();
if (factor == AVL.BALANCED)
{
avlFlag = false; //no more to do this time around
return tNode;
}
else if (factor == AVL.RIGHT)
{
return tNode; //no rotation necessary at this node, but need to keep checking upwards
}
AVLTreeNode right = tNode.getRight();
if (right.getBalanceFactor() == AVL.LEFT)
{
tNode = doubleRightLeft(tNode);
}
else
{
tNode = singleLeft(tNode);
}
avlFlag = false;
return tNode;
}
protected TreeNode deleteLeft(TreeNode tNode, Comparable sk)
{
tNode = super.deleteLeft(tNode, sk);
AVLTreeNode avltn = (AVLTreeNode) tNode;
if (avlFlag)
{
avltn = avlFixDeleteLeft(avltn);
}
return avltn;
}
protected TreeNode deleteRight(TreeNode tNode, Comparable sk)
{
tNode = super.deleteRight(tNode, sk);
AVLTreeNode avltn = (AVLTreeNode) tNode;
if (avlFlag)
{
avltn = avlFixDeleteRight(avltn);
}
return avltn;
}
protected TreeNode deleteNode(TreeNode tNode)
{
avlFlag = true;
tNode = super.deleteNode(tNode);
return tNode;
}
protected TreeNode deleteInorderSuccessor(TreeNode tNode)
{
tNode = super.deleteInorderSuccessor(tNode);
AVLTreeNode avltn = (AVLTreeNode) tNode;
if (avlFlag)
{
avltn = avlFixDeleteRight(avltn); //came from right
}
return avltn;
}
protected TreeNode deleteLeftmostt(TreeNode tNode)
{
tNode = super.deleteLeftmostt(tNode);
AVLTreeNode avltn = (AVLTreeNode) tNode;
if (avlFlag)
{
avltn = avlFixDeleteLeft(avltn);
}
return avltn;
}
//will be doing left rotations if coming back from the left on a delete
private AVLTreeNode avlFixDeleteLeft(AVLTreeNode tNode)
{
AVL factor = tNode.getBalanceFactor();
tNode.deleteLeft();
if (factor == AVL.BALANCED) //change from zero-- STOP
{
avlFlag = false; //no more to do this time around
return tNode;
}
factor = tNode.getBalanceFactor();
if (factor == AVL.RIGHT || factor == AVL.BALANCED)
{
return tNode; //need to keep checking, but no rotations necessary as yet
}
//rotations necessary for deleting a node
AVLTreeNode right = tNode.getRight();
AVL bF = right.getBalanceFactor();
if (bF == AVL.BALANCED)
{
tNode = singleLeft0(tNode);
}
else if (bF == AVL.RIGHT)
{
tNode = singleLeft(tNode);
}
else
{
tNode = doubleRightLeft(tNode);
}
return tNode;
}
private AVLTreeNode avlFixDeleteRight(AVLTreeNode tNode)
{
AVL factor = tNode.getBalanceFactor();
tNode.deleteRight();
if (factor == AVL.BALANCED) //change from zero-- STOP
{
avlFlag = false; //no more to do this time around
return tNode;
}
factor = tNode.getBalanceFactor();
if (factor == AVL.LEFT || factor == AVL.BALANCED)
{
return tNode; //need to keep checking, but no rotations necessary as yet
}
//rotations necessary for deleting a node
AVLTreeNode left = tNode.getLeft();
AVL bF = left.getBalanceFactor();
if (bF == AVL.BALANCED)
{
tNode = singleRight0(tNode);
}
else if (bF == AVL.LEFT)
{
tNode = singleRight(tNode);
}
else
{
tNode = doubleLeftRight(tNode);
}
return tNode;
}
private AVLTreeNode singleLeft0(AVLTreeNode tNode)
{
AVLTreeNode right = tNode.getRight();
tNode.setBalanceFactor(AVL.RIGHT);
right.setBalanceFactor(AVL.LEFT);
tNode = (AVLTreeNode) rotateLeft(tNode);
avlFlag = false; //STOP
//System.out.println("SL0");
return tNode;
}
private AVLTreeNode singleRight0(AVLTreeNode tNode)
{
AVLTreeNode left = tNode.getLeft();
tNode.setBalanceFactor(AVL.LEFT);
left.setBalanceFactor(AVL.RIGHT);
tNode = (AVLTreeNode) rotateRight(tNode);
avlFlag = false; //STOP
//System.out.println("SR0");
return tNode;
}
public void execute(Command command)
{
BinaryTreeIterator iter = iterator();
for(Iterator i =iter;i.hasNext();)
{
command.execute(i.next());
}
}
}
Program02/AVLTreeNode.java
Program02/AVLTreeNode.java
enum AVL {LEFT_HEAVY, LEFT, BALANCED, RIGHT, RIGHT_HEAVY};
public class AVLTreeNode extends TreeNode
{
private AVL balanceFactor;
public AVLTreeNode(Object item)
{
super(item);
balanceFactor = AVL.BALANCED;
}
public AVLTreeNode getLeft()
{
return (AVLTreeNode) super.getLeft();
}
public AVLTreeNode getRight()
{
return (AVLTreeNode) super.getRight();
}
public void setBalanceFactor(AVL avl)
{
balanceFactor = avl;
}
public AVL getBalanceFactor()
{
return balanceFactor;
}
public void insertLeft()
{
switch (balanceFactor)
{
case RIGHT:
balanceFactor = AVL.BALANCED;
break;
case BALANCED:
balanceFactor = AVL.LEFT;
break;
case LEFT:
balanceFactor = AVL.LEFT_HEAVY;
break;
}
}
public void insertRight()
{
switch (balanceFactor)
{
case RIGHT:
balanceFactor = AVL.RIGHT_HEAVY;
break;
case BALANCED:
balanceFactor = AVL.RIGHT;
break;
case LEFT:
balanceFactor = AVL.BALANCED;
break;
}
}
public void deleteLeft()
{
switch (balanceFactor)
{
case RIGHT:
balanceFactor = AVL.RIGHT_HEAVY;
break;
case BALANCED:
balanceFactor = AVL.RIGHT;
break;
case LEFT:
balanceFactor = AVL.BALANCED;
break;
}
}
public void deleteRight()
{
switch (balanceFactor)
{
case RIGHT:
balanceFactor = AVL.BALANCED;
break;
case BALANCED:
balanceFactor = AVL.LEFT;
break;
case LEFT:
balanceFactor = AVL.LEFT_HEAVY;
break;
}
}
}
Program02/BinarySearchTree.java
Program02/BinarySearchTree.java
/**
* This class stores KeyedItem data in a reference based binary search tree.
* A binary search tree is a binary tree (each node has 0, 1, or 2 children).
* In addition, all items on the left of a given node have search keys that are "less than" the item at the specified node.
* All items on the right of a given node have search keys that are "greater than" the item at the specified node.
*/
public class BinarySearchTree extends BinaryTreeBasis implements SearchTreeInterface
{
/** The number of KeyedItems stored in the binary search tree.
* Class invariant: should be the same as the number of nodes in the tree.
*/
private int size;
/** Constructs an empty binary search tree. */
public BinarySearchTree()
{
super();
}
public KeyedItem retrieve(Comparable sk)
{
return retrieveItem(getRootNode(), sk);
}
public void insert(KeyedItem item) throws TreeException
{
setRootNode(insertItem(getRootNode(), item));
size++;
assert validateBSTProperty() : "not a binary search tree after insertion of key: " + item.getKey();
assert validateSize() : "size is not correct after insertion of key: " + item.getKey();
}
public void delete(Comparable sk) throws TreeException
{
setRootNode(deleteItem(getRootNode(), sk));
size--;
assert validateBSTProperty() : "not a binary search tree after deletion of key: " + sk;
assert validateSize() : "size is not correct after deletion of key: " + sk;
}
/**
* Recursive method to retrieve an item from the binary search tree.
* Preconditions: tNode is not null, sk is not null
* Postconditions: the KeyedItem with the specified search key is returned, or null is returned if an item with the specified search key cannot be found
*/
protected KeyedItem retrieveItem(TreeNode tNode, Comparable sk)
{
//disallow duplicates so that you always know which object to retrieve (or delete)
//you could return a list with all duplicate search keys (but delete is still a problem)
KeyedItem treeItem;
if (tNode == null)
{
treeItem = null;
}
else
{
KeyedItem nodeItem = (KeyedItem) tNode.getItem();
int comparison = sk.compareTo(nodeItem.getKey());
if (comparison == 0)
{
treeItem = nodeItem;
}
else if (comparison < 0)
{
treeItem = retrieveItem(tNode.getLeft(), sk);
}
else
{
treeItem = retrieveItem(tNode.getRight(), sk);
}
}
return treeItem;
}
/**
* Creates and returns a new TreeNode to be linked into the tree.
* Precondition: item is not null
* Postcondition: a new TreeNode containing item is returned.
* Note: Should be overridden by child classes to create TreeNodes of the correct type.
*/
protected TreeNode createNode(KeyedItem item)
{
TreeNode tNode = new TreeNode(item);
return tNode;
}
/**
* Throws an exception if an attempt to insert an item with a search key that matches the
* search key of an item already in the tree.
* Override this method if duplicates are allowed in child classes.
* Throws: TreeException as an attempt to insert a duplicate was detected.
*/
protected TreeNode insertDuplicate(TreeNode tNode, KeyedItem item) throws TreeException
{
throw new TreeException ("Cannot add duplicate.");
}
/**
* Searches for the leaf insertion location for item.
* Precondition: item is not null
* Postcondition: returns the current node so that it can be linked (or relinked) to its parent
* depending on whether a left or a right was taken in obtaining the leaf insertion location.
* Throws: TreeException if an attempt to insert a duplicate is detected.
* Calls: insertLeft, insertRight, insertDuplicate depending on the item's sk
*/
protected TreeNode insertItem(TreeNode tNode, KeyedItem item) throws TreeException
{
if (tNode == null)
{
return createNode(item);
}
KeyedItem nodeItem = (KeyedItem) tNode.getItem();
int comparison = item.getKey().compareTo(nodeItem.getKey());
if (comparison == 0)
{
tNode = insertDuplicate(tNode, item);
}
else if (comparison < 0)
{
tNode = insertLeft(tNode, item);
}
else
{
tNode = insertRight(tNode, item);
}
return tNode;
}
/**
* A left hand turn must be dealt with to insert a node.
* Preconditions: tNode is not null, item is not null
* Postcondition: the child node is linked to tNode on the left, and tNode is returned to be linked in to its parent
* Note: this method makes a recursive call to insertItem
*/
protected TreeNode insertLeft(TreeNode tNode, KeyedItem item)
{
TreeNode subtree = insertItem(tNode.getLeft(), item);
tNode.setLeft(subtree);
return tNode;
}
protected TreeNode insertRight(TreeNode tNode, KeyedItem item)
{
TreeNode subtree = insertItem(tNode.getRight(), item);
tNode.setRight(subtree);
return tNode;
}
protected TreeNode deleteLeft(TreeNode tNode, Comparable sk)
{
TreeNode subtree = deleteItem(tNode.getLeft(), sk);
tNode.setLeft(subtree);
return tNode;
}
protected TreeNode deleteRight(TreeNode tNode, Comparable sk)
{
TreeNode subtree = deleteItem(tNode.getRight(), sk);
tNode.setRight(subtree);
return tNode;
}
protected TreeNode deleteItem(TreeNode tNode, Comparable sk) throws TreeException
{
if (tNode == null)
{
throw new TreeException("Item not found");
}
TreeNode subtree;
KeyedItem nodeItem = (KeyedItem)tNode.getItem();
int comparison = sk.compareTo(nodeItem.getKey());
if (comparison == 0)
{
// item is in the root of some subtree
tNode = deleteNode(tNode); // delete the item
}
// else search for the item
else if (comparison < 0)
{
tNode = deleteLeft(tNode, sk);
}
else
{
tNode = deleteRight(tNode, sk);
}
return tNode;
}
protected TreeNode deleteNode(TreeNode tNode)
{
TreeNode left = tNode.getLeft();
TreeNode right = tNode.getRight();
if (left == null)
{
return tNode.getRight();
}
else if (right == null)
{
return tNode.getLeft();
}
// there are two children:
// retrieve and delete the inorder successor
else
{
return deleteInorderSuccessor(tNode);
}
}
protected TreeNode deleteInorderSuccessor(TreeNode tNode)
{
TreeNode right = tNode.getRight();
KeyedItem replacementItem = findLeftmost(right);
tNode.setItem(replacementItem);
TreeNode subtree = deleteLeftmost(tNode.getRight());
tNode.setRight(subtree);
return tNode;
}
protected KeyedItem findLeftmost(TreeNode tNode)
{
if (tNode.getLeft() == null)
{
return (KeyedItem) tNode.getItem();
}
else
{
return findLeftmost(tNode.getLeft());
}
}
protected TreeNode deleteLeftmostt(TreeNode tNode)
{
TreeNode subtree = deleteLeftmost(tNode.getLeft());
tNode.setLeft(subtree);
return tNode;
}
protected TreeNode deleteLeftmost(TreeNode tNode)
{
if (tNode.getLeft() == null)
{
return tNode.getRight();
}
else
{
return deleteLeftmostt(tNode);
}
}
protected TreeNode rotateLeft(TreeNode tNode)
{
TreeNode right = tNode.getRight();
TreeNode rightleft = right.getLeft();
tNode.setRight(rightleft);
right.setLeft(tNode);
return right;
}
protected TreeNode rotateRight(TreeNode tNode)
{
TreeNode left = tNode.getLeft();
TreeNode leftright = left.getRight();
tNode.setLeft(leftright);
left.setRight(tNode);
return left;
}
public boolean isBalanced()
{
return isBalanced(getRootNode());
}
private boolean isBalanced(TreeNode tNode)
{
if (tNode == null)
{
return true;
}
boolean balanced = isBalanced(tNode.getLeft());
if (!balanced) return balanced;
balanced = isBalanced(tNode.getRight());
if (!balanced) return balanced;
int leftHeight = getHeight(tNode.getLeft());
int rightHeight = getHeight(tNode.getRight());
if (Math.abs(leftHeight - rightHeight) > 1)
{
balanced = false;
}
return balanced;
}
public int height()
{
return getHeight(getRootNode());
}
private int getHeight(TreeNode tNode)
{
if (tNode == null)
{
return 0;
}
int height = 0;
int leftHeight = getHeight(tNode.getLeft());
int rightHeight = getHeight(tNode.getRight());
if (leftHeight >= rightHeight)
{
height = leftHeight + 1;
}
else
{
height = rightHeight + 1;
}
return height;
}
public int size()
{
return size;
}
public int computeSize()
{
int num = 0;
TreeIterator iter = iterator();
iter.setInorder();
while (iter.hasNext())
{
KeyedItem item = (KeyedItem) iter.next();
num++;
}
return num;
}
public boolean validateSize()
{
return size() == computeSize();
}
public boolean validateBSTProperty()
{
TreeIterator iter = iterator();
iter.setInorder();
boolean valid = true;
//an empty tree satisfies the BST property by definition
if (!iter.hasNext()) return true;
KeyedItem item1 = (KeyedItem) iter.next();
Comparable key1 = item1.getKey();
while (iter.hasNext())
{
KeyedItem item2 = (KeyedItem) iter.next();
Comparable key2 = item2.getKey();
//key1 must be <= key2 for BST property
if (key1.compareTo(key2) > 0)
{
valid = false;
break;
}
item1 = item2;
key1 = key2;
}
return valid;
}
}
Program02/BinaryTreeBasis.java
Program02/BinaryTreeBasis.java
import java.util.Iterator;
public abstract class BinaryTreeBasis
{
private TreeNode root;
public BinaryTreeBasis()
{
root = null;
}
public boolean isEmpty()
{
return root == null;
}
public void makeEmpty()
{
root = null;
}
public Object getRootItem() throws TreeException
{
if (root == null)
{
throw new TreeException("Empty tree");
}
else
{
return root.getItem();
}
}
protected TreeNode getRootNode()
{
return root;
}
protected void setRootNode(TreeNode tNode)
{
root = tNode;
}
public BinaryTreeIterator iterator()
{
BinaryTreeIterator bti = new BinaryTreeIterator(root);
bti.setInorder();
return bti;
}
}
Program02/BinaryTreeIterator.java
Program02/BinaryTreeIterator.java
import queue.*;
class BinaryTreeIterator implements TreeIterator
{
private TreeNode root;
private QueueInterface items;
public BinaryTreeIterator(TreeNode root)
{
this.root = root;
items = new QueueLinked();
}
public boolean hasNext()
{
return !items.isEmpty();
}
public Object next() throws TreeException
{
try
{
return items.dequeue();
}
catch (QueueException e)
{
throw new TreeException("End of tree traversal.");
}
}
public void remove() throws UnsupportedOperationException
{
throw new UnsupportedOperationException();
}
public void setPreorder()
{
items.dequeueAll();
preorder(root);
}
public void setInorder()
{
items.dequeueAll();
inorder(root);
}
public void setPostorder()
{
items.dequeueAll();
postorder(root);
}
private void preorder(TreeNode tNode)
{
if (tNode != null)
{
items.enqueue(tNode.getItem());
preorder(tNode.getLeft());
preorder(tNode.getRight());
}
}
private void inorder(TreeNode tNode)
{
if (tNode != null)
{
inorder(tNode.getLeft());
items.enqueue(tNode.getItem());
inorder(tNode.getRight());
}
}
private void postorder(TreeNode tNode)
{
if (tNode != null)
{
postorder(tNode.getLeft());
postorder(tNode.getRight());
items.enqueue(tNode.getItem());
}
}
public void setLevelorder()
{
if (root != null)
{
QueueInterface
q = new QueueLinked();
q.enqueue(root);
while (!q.isEmpty())
{
TreeNode tNode = q.dequeue();
items.enqueue(tNode.getItem());
TreeNode left = tNode.getLeft();
TreeNode right = tNode.getRight();
if (left != null)
{
q.enqueue(left);
}
if (right != null)
{
q.enqueue(right);
}
}
}
}
}
Program02/CD.java
Program02/CD.java
import java.util.ArrayList;
public class CD extends KeyedItem
{
private int year;
private String img;
private ArrayList songs;
private int numTracks; //used by addSong
private int rating;
public CD (String title, String artist, int year, int rating, int tracks)
{
super(title);
this.year = year;
img = artist + " - " + getKey() + ".jpg";
numTracks = tracks;
songs = new ArrayList();
if (rating > 0 && rating <= 10)
{
this.rating = rating;
}
else
{
this.rating = 5;
}
}
public int getNumberOfTracks()
{
return songs.size();
}
public int getYear()
{
return year;
}
public int getRating()
{
return rating;
}
//Song is immutable, so this is safe
public Song getSong(int index)
{
if (index >= 0 && index < songs.size())
{
return songs.get(index);
}
else
{
return null;
}
}
public void addSong(String title, String length)
{
if (songs.size() < numTracks)
{
songs.add(new Song(title, length));
}
}
public String toString()
{
return getKey() + " " + year + " " + rating + " " + getNumberOfTracks();
}
public void writeCD(FileIO file)
{
if (rating == 10)
{
file.writeLine("" + "" + getKey() + "" + "");
}
else
{
file.writeLine("" + getKey() + "");
}
file.writeLine("");
file.writeLine("");
file.writeLine("- Year: " + year + "
");
file.writeLine("- Rating: " + rating + "
");
file.writeLine("- Tracks:
");
file.writeLine("");
file.writeLine("Track | Title | Length |
");
int count = 0;
for (Song song : songs)
{
file.writeLine("");
song.writeSong(file, ++count);
file.writeLine("
");
}
file.writeLine("
");
file.writeLine("
");
}
}
Program02/cds.txt
Dark Tranquillity
We Are The Void
2010
8
13
3:46,Shadow in Our Blood
3:48,Dream Oblivion
4:32,The Fatalist
4:46,In My Absence
4:55,The Grandest Accusation
3:52,At the Point of Ignition
3:33,Her Silent Language
3:56,Arkhangelsk
3:59,I Am the Void
3:50,Surface the Infinite
6:43,Iridium
2:07,Star of Nothingness
3:53,To Where Fires Cannot Feed
Asphyx
Death...The Brutal Way
2009
7
10
4:26,Scorbutics
3:33,The Herald
3:56,Bloodswamp
3:52,Death...The Brutal Way
6:40,Asphyx II (They Died As They Marched)
5:42,Eisenbahnmörser
5:35,Black Hole Storm
5:04,Riflegun Redeemer
6:53,Cape Horn
3:11,The Saw, The Torture, The Pain
Kalmah
12 Gauge
2010
9
10
5:16,Rust Never Sleeps
4:10,One Of Fail
4:27,Bullets Are Blind
4:19,Swampwar
3:58,Better Not To Tell
4:04,Hook The Monster
4:25,Godeye
5:50,12 Gauge
6:28,Sacramentum
3:10,Cold Sweat
Absu
Absu
2009
9
13
4:08,Between The Absu Of Eridu & Erech
3:19,Night Fire Canonization
4:54,Amy
3:05,Nunbarshegunu
4:46,13 Globes
7:03,...Of The Dead Who Never Rest In Their Tombs Are The Attendance Of Familiar Spirits...
4:48,Magic(K) Square Cipher
3:25,In The Name Of Auebothiabathabaithobeuee
2:38,Girra's Temple
4:56,Those Of The Void Will Re-Enter
5:00,Sceptre Command
4:41,Ye Uttuku Spells
0:58,Twix Yesterday The Day & The Morrow
Augury
Fragmentary Evidence
2009
9
9
4:18,Aetheral
5:37,Simian Cattle
5:10,Orphans of Living
8:24,Jupiter to Ignite
5:12,Sovereigns Unknown
6:29,Skyless
4:06,Faith Puppeteers
4:30,Brimstone Landscapes
11:12,Oversee the Rebirth
Immolation
Majesty And Decay
2010
9
12
1:19,Intro
3:18,The Purge
2:41,A Token Of Malice
4:29,Majesty And Decay
3:38,Divine Code
4:04,In Human Form
4:37,A Glorious Epoch
2:04,Interlude
3:58,A Thunderous Consequence
5:19,The Rapture Of Ghosts
3:44,Power And Shame
5:53,The Comfort Of Cowards
Skyfire
Esoteric
2009
7
11
1:26,Deathlike Overture
4:44,Esoteric
6:10,Rise and Decay
4:10,Let the Old World Burn
7:09,Darkness Descending
3:56,Seclusion
7:10,Misery's Supremacy
4:52,Under A Pitch Black Sky
5:18,Linger in Doubt
7:21,The Legacy of the Defeated
3:36,Within Reach
Neuraxis
Trilateral Progression
2005
8
10
0:38,Introspect
3:30,Clarity
5:15,Thought Adjuster
4:27,Shatter The Wisdom
3:42,Monitoring The Mind
3:42,A Curative Struggle
4:25,Chamber Of Gaurdians
1:39,Caricature
1:52,Axioms
6:00,The Apex
Insomnium
Across The...