Write a Java class called Song to represent a song in a music collection. The da
ID: 3699804 • Letter: W
Question
Write a Java class called Song to represent a song in a music collection. The data members of the Song class are String objects representing the song title, artist’s name, and the album that includes the song. The instance variables for the class are to have private access modifiers, so you will need to write the appropriate methods to allow a client class to access and modify the data values. In accordance with good programming practice, you are to override the equals and toString methods inherited from Object. In addition, this class is going to be used in a future project collection that is to be sorted, so you’ll need to implement the Comparable interface. A second class is to be written called SongReader that contains a main method that reads in a file name via the command line. The file is a listing of the songs that have been formatted using angle-bracketed tags. For example
the trapeze swinger iron & wine the trapeze swinger - single
Each line will a tag (opening or closing), data, or a combination of these elements. Tags are matched pairs of single
words surrounded by angle brackets. Opening tags begin with an angle bracket (<) and closing tags begin with an
angle bracket and forward slash ( inside song tags.
Input is read by the SongReader class. When reading the input file, data that is not specifically enclosed in song, title, artist, or album tags is to be ignored. The name of the input file will be provided as a command line argument. If the file name is missing or the file cannot be opened, the program should prompt the user to enter a new file name.
Any incorrectly formatted song data should be collected in a report and printed out in an error report to a file called ErrorLog.txt. error log should be in the same format as given data, returning the entirety of the bad "song'' not just where the error is occuring. tags must be exactly as shown in example and cannot overlap inside each other. extra data outside of tags in inside song tag specifically may be ignored. In the example shown above the first two songs are correctly formatted, but the third one is not because the artist tag is inside of the title tag. As another example, in the sample input file, playlist.data, the first five song items are valid but the last one is invalid and should be reported as an error by the SongReader program
The SongReader class will open and read the input file to create Song objects by parsing the file data. You are required to use an implementation of the given StackInterface interface in your project for matching opening and closing tags. You do not have to implement the interface, you may use one of the implementations that we have discussed in class and can be found in the Stacks content area of Blackboard. You may not use any external parsing libraries. After reading the input, the SongReader class will display a list of the valid Song objects. (Note that your code must create a collection of Song objects and iterate over the collection to display the information.)
It is expected that your program will be well documented and you are required to write a private helper method called printHeading in the SongReader class that outputs the following information to the console in an easy-toread format: your name, the project number, the course identifier (CMSC 256), and the current semester. You will call this method as the first statement in your main method. All files must contain a comment block at the beginning that includes the file name; all of the same information that was specified for the helper method printHeading; and a brief description of the file’s purpose. should be two seperate files, song.java and songReader.java
Stack Implementation :
import java.util.EmptyStackException;
public class LinkedStack<T> implements StackInterface<T> {
private Node topNode;
public LinkedStack() {
topNode = null;
}
private class Node {
private T data;
private Node next;
private Node(T d, Node n) {
data = d;
next = n;
}
private T getData() {
return data;
}
private Node getNextNode() {
return next;
}
}
@Override
public void push(T newEntry) {
topNode = new Node(newEntry, topNode);
}
@Override
public T pop() {
if(isEmpty()) {
throw new EmptyStackException();
}
T top = topNode.getData();
topNode = topNode.getNextNode();
return top;
}
@Override
public T peek() {
if(isEmpty()) {
throw new EmptyStackException();
}
return topNode.getData();
}
@Override
public boolean isEmpty() {
return topNode == null;
}
@Override
public void clear() {
topNode = null;
}
}
Explanation / Answer
import java.util.Scanner;
import java.io.File;
import java.util.EmptyStackException;
import java.util.NoSuchElementException;
import java.io.FileNotFoundException;
import java.lang.IllegalArgumentException;
public class SongReader {
private static LinkedStack<String> tagStack = new LinkedStack<String>();
private static Song currentSong = new Song();
public static void main(String[] args) {
printHeading();
try{
Scanner fileReader = openFile();
String nextLine = fileReader.nextLine().trim();
String previousLine = "";
while(fileReader.hasNextLine()) {
if (previousLine.startsWith("<") && previousLine.endsWith(">")
&& !(previousLine.startsWith("</")) ) {
try {
addToTagStack(previousLine, nextLine);
}
catch(IllegalArgumentException nullArgument) {
while(!previousLine.equalsIgnoreCase("</song>")) { // Iterates until end of current song
previousLine = fileReader.nextLine().trim(); // Moves the scanner down the file
} // end of while
} // end of catch
catch(NullPointerException e) {
}
} // end of if
if(previousLine.startsWith("</") && previousLine.endsWith(">")) { // Checks if previous line was a closing tag
closeTag(previousLine);
}
previousLine = nextLine; // Saves the value of the current line so it can be used in future iterations
try{
nextLine = fileReader.nextLine().trim();
}
catch(NoSuchElementException e){
}
} // end of while loop
} // end of try
catch(FileNotFoundException noFile){
System.out.println("There was an error opening or reading from the file.");
}
}
//Adds the parameter to the stack of tags if it denotes a title, artist, or album,
private static void addToTagStack(String previousLine, String nextLine) throws IllegalArgumentException {
if(previousLine.equalsIgnoreCase("<title>")) {
tagStack.push(previousLine);
if(nextLine.equals("") || nextLine.equalsIgnoreCase("</title>") || nextLine.equals(null)) {
throw new IllegalArgumentException("Songs cannot have null fields.");
}
else {
currentSong.setTitle(nextLine);
}
}
if(previousLine.equalsIgnoreCase("<album>")) {
tagStack.push(previousLine);
if(nextLine.equals("") || nextLine.equalsIgnoreCase("</album>") || nextLine.equals(null)) {
throw new IllegalArgumentException("Songs cannot have null fields.");
}
else {
currentSong.setAlbum(nextLine);
}
}
if(previousLine.equalsIgnoreCase("<artist>")) {
tagStack.push(previousLine);
if(nextLine.equals("") || nextLine.equalsIgnoreCase("</artist>") || nextLine.equals(null)) {
throw new IllegalArgumentException("Songs cannot have null fields.");
}
else {
currentSong.setArtist(nextLine);
}
}
}
//Removes the previous tag from the top of the stack if it matches the song, title, artist, or album tag parameter.
private static void closeTag(String previousLine) {
if(previousLine.equalsIgnoreCase("</song>")) {
endSong();
}
try {
if(previousLine.equalsIgnoreCase("</title>")) {
if (tagStack.peek().equalsIgnoreCase("<title>")) {
tagStack.pop();
}
else {
throw new IllegalArgumentException("Tags improperly closed.");
}
}
if(previousLine.equalsIgnoreCase("</album>")) {
if (tagStack.peek().equalsIgnoreCase("<album>")) {
tagStack.pop();
}
else {
throw new IllegalArgumentException("Tags improperly closed.");
}
}
if(previousLine.equalsIgnoreCase("</artist>")) {
if (tagStack.peek().equalsIgnoreCase("<artist>")) {
tagStack.pop();
}
else {
throw new IllegalArgumentException("Tags improperly closed.");
}
}
}
catch(IllegalArgumentException BadTags) {
} // No action necessary
}
//Prints the current song object and resets it for any future songs.
private static void endSong() {
try {
System.out.println(currentSong.toString());
if (!tagStack.pop().equalsIgnoreCase("<song>")) {
throw new IllegalArgumentException("A tag was left unclosed.");
}
}
// catch(IllegalArgumentException BadTag) {
// tagStack.clear();
// }
catch(EmptyStackException e) {
}
assert (tagStack.isEmpty());
Song blankSong = new Song(); //Resets song data between songs
currentSong = blankSong;
}
// Prompts the user for a filepath, and scans the console for a response.
private static String promptForFilePath() {
System.out.println("Enter the file path: ");
Scanner input = new Scanner(System.in);
String f = input.nextLine();
input.close();
return f;
}
//Verify that the file exists, then creates a scanner to read it.
private static Scanner openFile() throws FileNotFoundException {
File file = new File("");
file = new File(promptForFilePath());
return new Scanner(file);
}
// Prints a heading about the program to the console.
private static void printHeading() {
System.out.println("Song Reader");
}
}
-----------------------------------------------------------------
public class Song implements Comparable<Song> {
private String title;
private String artist;
private String album;
public Song() {
setTitle("");
setArtist("");
setAlbum("");
}
public Song(String title, String artist, String album) {
setTitle(title);
setArtist(artist);
setAlbum(album);
}
//Gets the song title.
public String getTitle() {
return title;
}
// Set and trim the song title.
public void setTitle(String ti) {
try{
title = ti.trim();
}
catch(NullPointerException nullArg) {
title = "";
}
}
// Gets the song artist.
public String getArtist() {
return artist;
}
//Set and trim the song artist.
public void setArtist(String ar) {
try{
artist = ar.trim();
}
catch(NullPointerException nullArg) {
artist = "";
}
}
//Gets the song album.
public String getAlbum() {
return album;
}
// Sets and trims the song album.
public void setAlbum(String al) {
try{
album = al.trim();
}
catch(NullPointerException nullArg) {
album = "";
}
}
// Checks if this song's title, artist, and album match that of the argument song.
@Override
public boolean equals(Object arg) {
if(arg == null) {
return false;
}
else if(this == arg) {
return true;
}
else if(!(arg instanceof Song)) {
return false;
}
Song other = (Song) arg;
if(this.getTitle().equalsIgnoreCase(other.getTitle()) &&
this.getAlbum().equalsIgnoreCase(other.getAlbum()) &&
this.getArtist().equalsIgnoreCase(other.getArtist())) {
return true;
}
return false;
}
/// Converts the song to a string by combining the title, artist, and album.
@Override
public String toString() {
return "Title: " + getTitle() + " Artist: " + getArtist() + " Album: " + getAlbum() + " ";
}
// Compares this song's album and title lexicographically to those of the argument.
@Override
public int compareTo(Song arg) throws NullPointerException {
if(arg == null) {
throw new NullPointerException();
}
int albumCompResult = this.getAlbum().compareToIgnoreCase(arg.getAlbum());
if(albumCompResult != 0){
return albumCompResult;
}
else { // albums are equal
int titleCompResult = this.getTitle().compareToIgnoreCase(arg.getTitle());
if (titleCompResult != 0) {
return titleCompResult;
}
else { // titles are equal
return this.getArtist().compareToIgnoreCase(arg.getArtist());
}
}
}
}
---------------------------------------------------------------------------------
import java.util.EmptyStackException;
public final class LinkedStack<T> implements StackInterface<T>
{
private Node topNode;
public LinkedStack()
{
topNode = null;
} // end default constructor
public void push(T newEntry)
{
topNode = new Node(newEntry, topNode);
// Node newNode = new Node(newEntry, topNode);
// topNode = newNode;
} // end push
public T peek()
{
if (isEmpty())
throw new EmptyStackException();
else
return topNode.getData();
} // end peek
public T pop()
{
T top = peek(); // Might throw EmptyStackException
assert (topNode != null);
topNode = topNode.getNextNode();
return top;
} // end pop
public boolean isEmpty()
{
return topNode == null;
} // end isEmpty
public void clear()
{
topNode = null; // Causes deallocation of nodes in the chain
} // end clear
private class Node
{
private T data; // Entry in stack
private Node next; // Link to next node
private Node(T dataPortion)
{
this(dataPortion, null);
} // end constructor
private Node(T dataPortion, Node linkPortion)
{
data = dataPortion;
next = linkPortion;
} // end constructor
private T getData()
{
return data;
} // end getData
// private void setData(T newData)
// {
// data = newData;
// } // end setData
private Node getNextNode()
{
return next;
} // end getNextNode
// private void setNextNode(Node nextNode)
// {
// next = nextNode;
// } // end setNextNode
} // end Node
} // end LinkedStack
-----------------------------------------------------------------
public interface StackInterface<T>
{
//Adds a new entry to the top of this stack.
public void push(T newEntry);
//Removes and returns this stack's top entry.
public T pop();
// Retrieves this stack's top entry.
public T peek();
// Detects whether this stack is empty.
public boolean isEmpty();
// Removes all entries from this stack.
public void clear();
} // end StackInterface
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.