aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/musichub
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/musichub')
-rw-r--r--src/main/java/musichub/business/Album.java145
-rw-r--r--src/main/java/musichub/business/AudioBook.java78
-rw-r--r--src/main/java/musichub/business/AudioElement.java132
-rw-r--r--src/main/java/musichub/business/Category.java14
-rw-r--r--src/main/java/musichub/business/Genre.java14
-rw-r--r--src/main/java/musichub/business/Language.java14
-rw-r--r--src/main/java/musichub/business/MusicHub.java405
-rw-r--r--src/main/java/musichub/business/NoAlbumFoundException.java8
-rw-r--r--src/main/java/musichub/business/NoElementFoundException.java8
-rw-r--r--src/main/java/musichub/business/NoPlayListFoundException.java8
-rw-r--r--src/main/java/musichub/business/PlayList.java100
-rw-r--r--src/main/java/musichub/business/Song.java58
-rw-r--r--src/main/java/musichub/main/Main.java335
-rw-r--r--src/main/java/musichub/util/LogHandler.java68
-rw-r--r--src/main/java/musichub/util/PathValidation.java49
-rw-r--r--src/main/java/musichub/util/Policy.java76
-rw-r--r--src/main/java/musichub/util/XMLHandler.java74
17 files changed, 1586 insertions, 0 deletions
diff --git a/src/main/java/musichub/business/Album.java b/src/main/java/musichub/business/Album.java
new file mode 100644
index 0000000..01fd179
--- /dev/null
+++ b/src/main/java/musichub/business/Album.java
@@ -0,0 +1,145 @@
+package musichub.business;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+
+public class Album {
+ private final String title;
+ private final int lengthInSeconds;
+ private final UUID uuid;
+ private String artist;
+ private Date date;
+ private ArrayList<UUID> songsUIDs;
+
+ public Album(String title, String artist, int lengthInSeconds, String id, String date, ArrayList<UUID> songsUIDs) {
+ this.title = title;
+ this.artist = artist;
+ this.lengthInSeconds = lengthInSeconds;
+ this.uuid = UUID.fromString(id);
+ try {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ this.date = sdf.parse(date);
+ } catch (ParseException ex) {
+ ex.printStackTrace();
+ }
+ this.songsUIDs = songsUIDs;
+ }
+
+ public Album(String title, String artist, int lengthInSeconds, String date) {
+ this.title = title;
+ this.artist = artist;
+ this.lengthInSeconds = lengthInSeconds;
+ this.uuid = UUID.randomUUID();
+ try {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ this.date = sdf.parse(date);
+ } catch (ParseException ex) {
+ ex.printStackTrace();
+ }
+ this.songsUIDs = new ArrayList<>();
+ }
+
+ public Album(Element xmlElement) throws Exception {
+ {
+ this.title = xmlElement.getElementsByTagName("title").item(0).getTextContent();
+ this.lengthInSeconds = Integer.parseInt(xmlElement.getElementsByTagName("lengthInSeconds").item(0).getTextContent());
+ String uuid = null;
+ try {
+ uuid = xmlElement.getElementsByTagName("UUID").item(0).getTextContent();
+ } catch (Exception ex) {
+ System.out.println("Empty album UUID, will create a new one");
+ }
+ if ((uuid == null) || (uuid.isEmpty()))
+ this.uuid = UUID.randomUUID();
+ else this.uuid = UUID.fromString(uuid);
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ this.date = sdf.parse(xmlElement.getElementsByTagName("date").item(0).getTextContent());
+ //parse list of songs:
+ Node songsElement = xmlElement.getElementsByTagName("songs").item(0);
+ NodeList songUUIDNodes = songsElement.getChildNodes();
+ if (songUUIDNodes == null) return;
+
+ this.songsUIDs = new ArrayList<>();
+
+ for (int i = 0; i < songUUIDNodes.getLength(); i++) {
+ if (songUUIDNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
+ Element songElement = (Element) songUUIDNodes.item(i);
+ if (songElement.getNodeName().equals("UUID")) {
+ try {
+ this.addSong(UUID.fromString(songElement.getTextContent()));
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ public void addSong(UUID song) {
+ songsUIDs.add(song);
+ }
+
+
+ public List<UUID> getSongs() {
+ return songsUIDs;
+ }
+
+ public ArrayList<UUID> getSongsRandomly() {
+ ArrayList<UUID> shuffledSongs = songsUIDs;
+ Collections.shuffle(shuffledSongs);
+ return shuffledSongs;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void createXMLElement(Document document, Element parentElement) {
+ Element albumElement = document.createElement("album");
+ parentElement.appendChild(albumElement);
+
+ Element nameElement = document.createElement("title");
+ nameElement.appendChild(document.createTextNode(title));
+ albumElement.appendChild(nameElement);
+
+ Element artistElement = document.createElement("artist");
+ artistElement.appendChild(document.createTextNode(artist));
+ albumElement.appendChild(artistElement);
+
+ Element lengthElement = document.createElement("lengthInSeconds");
+ lengthElement.appendChild(document.createTextNode(Integer.valueOf(lengthInSeconds).toString()));
+ albumElement.appendChild(lengthElement);
+
+ Element UUIDElement = document.createElement("UUID");
+ UUIDElement.appendChild(document.createTextNode(uuid.toString()));
+ albumElement.appendChild(UUIDElement);
+
+ Element dateElement = document.createElement("date");
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ dateElement.appendChild(document.createTextNode(sdf.format(date)));
+ albumElement.appendChild(dateElement);
+
+ Element songsElement = document.createElement("songs");
+ for (UUID currentUUID : this.songsUIDs) {
+ Element songUUIDElement = document.createElement("UUID");
+ songUUIDElement.appendChild(document.createTextNode(currentUUID.toString()));
+ songsElement.appendChild(songUUIDElement);
+ }
+ albumElement.appendChild(songsElement);
+
+ }
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/AudioBook.java b/src/main/java/musichub/business/AudioBook.java
new file mode 100644
index 0000000..80392d6
--- /dev/null
+++ b/src/main/java/musichub/business/AudioBook.java
@@ -0,0 +1,78 @@
+package musichub.business;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class AudioBook extends AudioElement {
+ private Language language;
+ private Category category;
+
+ public AudioBook(String title, String artist, int lengthInSeconds, String uid, String content, String language, String category) {
+ super(title, artist, lengthInSeconds, uid, content);
+ this.setLanguage(language);
+ this.setCategory(category);
+ }
+
+ public AudioBook(String title, String artist, int lengthInSeconds, String content, String language, String category) {
+ super(title, artist, lengthInSeconds, content);
+ this.setLanguage(language);
+ this.setCategory(category);
+ }
+
+ public AudioBook(Element xmlElement) {
+ super(xmlElement);
+ this.setLanguage(xmlElement.getElementsByTagName("language").item(0).getTextContent());
+ this.setCategory(xmlElement.getElementsByTagName("category").item(0).getTextContent());
+ }
+
+ public Language getLanguage() {
+ return this.language;
+ }
+
+ public void setLanguage(String language) {
+ switch (language.toLowerCase()) {
+ default -> this.language = Language.ENGLISH;
+ case "french" -> this.language = Language.FRENCH;
+ case "german" -> this.language = Language.GERMAN;
+ case "spanish" -> this.language = Language.SPANISH;
+ case "italian" -> this.language = Language.ITALIAN;
+ }
+ }
+
+ public Category getCategory() {
+ return this.category;
+ }
+
+ public void setCategory(String category) {
+ switch (category.toLowerCase()) {
+ default -> this.category = Category.YOUTH;
+ case "novel" -> this.category = Category.NOVEL;
+ case "theater" -> this.category = Category.THEATER;
+ case "documentary" -> this.category = Category.DOCUMENTARY;
+ case "speech" -> this.category = Category.SPEECH;
+ }
+ }
+
+
+ public String toString() {
+ return super.toString() + ", Language = " + getLanguage() + ", Category = " + getCategory() + "\n";
+ }
+
+
+ public void createXMLElement(Document document, Element parentElement) {
+ // audiobook element
+ Element audioBook = document.createElement("audiobook");
+
+ super.createXMLElement(document, audioBook);
+
+ Element languageElement = document.createElement("language");
+ languageElement.appendChild(document.createTextNode(language.getLanguage()));
+ audioBook.appendChild(languageElement);
+
+ Element categoryElement = document.createElement("category");
+ categoryElement.appendChild(document.createTextNode(category.getCategory()));
+ audioBook.appendChild(categoryElement);
+
+ parentElement.appendChild(audioBook);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/AudioElement.java b/src/main/java/musichub/business/AudioElement.java
new file mode 100644
index 0000000..80a649a
--- /dev/null
+++ b/src/main/java/musichub/business/AudioElement.java
@@ -0,0 +1,132 @@
+package musichub.business;
+
+import musichub.util.LogHandler;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.sound.sampled.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.Scanner;
+import java.util.UUID;
+
+public abstract class AudioElement {
+ protected String title;
+ protected String artist;
+ protected int lengthInSeconds;
+ protected UUID uuid;
+ protected String content;
+
+ public AudioElement(String title, String artist, int lengthInSeconds, String id, String content) {
+ this.title = title;
+ this.artist = artist;
+ this.lengthInSeconds = lengthInSeconds;
+ this.uuid = UUID.fromString(id);
+ this.content = content;
+ }
+
+ public AudioElement(String title, String artist, int lengthInSeconds, String content) {
+ this.title = title;
+ this.artist = artist;
+ this.lengthInSeconds = lengthInSeconds;
+ this.content = content;
+ this.uuid = UUID.randomUUID();
+ }
+
+ public AudioElement(Element xmlElement) {
+ {
+ title = xmlElement.getElementsByTagName("title").item(0).getTextContent();
+ artist = xmlElement.getElementsByTagName("artist").item(0).getTextContent();
+ lengthInSeconds = Integer.parseInt(xmlElement.getElementsByTagName("length").item(0).getTextContent());
+ content = xmlElement.getElementsByTagName("content").item(0).getTextContent();
+ String uuid = null;
+ try {
+ uuid = xmlElement.getElementsByTagName("UUID").item(0).getTextContent();
+ } catch (Exception ex) {
+ System.out.println("Empty element UUID, will create a new one");
+ }
+ if ((uuid == null) || (uuid.isEmpty()))
+ this.uuid = UUID.randomUUID();
+ else this.uuid = UUID.fromString(uuid);
+ }
+ }
+
+ public UUID getUUID() {
+ return this.uuid;
+ }
+
+ public String getArtist() {
+ return this.artist;
+ }
+
+ public String getTitle() {
+ return this.title;
+ }
+
+ public String toString() {
+ return "Title = " + this.title + ", Artist = " + this.artist + ", Length = " + this.lengthInSeconds + ", Content = " + this.content;
+ }
+
+ public void createXMLElement(Document document, Element parentElement) {
+ Element nameElement = document.createElement("title");
+ nameElement.appendChild(document.createTextNode(title));
+ parentElement.appendChild(nameElement);
+
+ Element artistElement = document.createElement("artist");
+ artistElement.appendChild(document.createTextNode(artist));
+ parentElement.appendChild(artistElement);
+
+ Element lengthElement = document.createElement("length");
+ lengthElement.appendChild(document.createTextNode(Integer.valueOf(lengthInSeconds).toString()));
+ parentElement.appendChild(lengthElement);
+
+ Element UUIDElement = document.createElement("UUID");
+ UUIDElement.appendChild(document.createTextNode(uuid.toString()));
+ parentElement.appendChild(UUIDElement);
+
+ Element contentElement = document.createElement("content");
+ contentElement.appendChild(document.createTextNode(content));
+ parentElement.appendChild(contentElement);
+
+ }
+
+ public void manageAudioElement() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
+
+ Scanner scanner = new Scanner(System.in);
+
+ File file = new File(this.content);
+ AudioInputStream audioStream = AudioSystem.getAudioInputStream(file);
+ Clip clip = AudioSystem.getClip();
+ clip.open(audioStream);
+
+ String action = "";
+
+ while(!action.equals("Q")) {
+ System.out.println("P = Play \b S = Stop \b R = Reset \b Q = Quit");
+ System.out.println("Enter your choice");
+ action = scanner.next();
+ action = action.toUpperCase();
+
+ switch (action) {
+ case "S", "Q" -> {
+ clip.stop();
+ LogHandler.write("Music stopped", "INFO");
+ }
+ case "P" -> {
+ clip.start();
+ LogHandler.write("Music started", "INFO");
+ }
+ case "R" -> {
+ clip.setMicrosecondPosition(0);
+ LogHandler.write("Music reseted", "INFO");
+ }
+ default -> System.out.println("try again");
+ }
+ System.out.println("You stopped the Audio element");
+ }
+
+ clip.close();
+
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/Category.java b/src/main/java/musichub/business/Category.java
new file mode 100644
index 0000000..f676e51
--- /dev/null
+++ b/src/main/java/musichub/business/Category.java
@@ -0,0 +1,14 @@
+package musichub.business;
+
+public enum Category {
+ YOUTH("youth"), NOVEL("novel"), THEATER("theater"), DOCUMENTARY("documentary"), SPEECH("speech");
+ private final String category;
+
+ Category(String category) {
+ this.category = category;
+ }
+
+ public String getCategory() {
+ return category;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/Genre.java b/src/main/java/musichub/business/Genre.java
new file mode 100644
index 0000000..18deca6
--- /dev/null
+++ b/src/main/java/musichub/business/Genre.java
@@ -0,0 +1,14 @@
+package musichub.business;
+
+public enum Genre {
+ JAZZ("jazz"), CLASSIC("classic"), HIPHOP("hiphop"), ROCK("rock"), POP("pop"), RAP("rap");
+ private final String genre;
+
+ Genre(String genre) {
+ this.genre = genre;
+ }
+
+ public String getGenre() {
+ return genre;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/Language.java b/src/main/java/musichub/business/Language.java
new file mode 100644
index 0000000..679e586
--- /dev/null
+++ b/src/main/java/musichub/business/Language.java
@@ -0,0 +1,14 @@
+package musichub.business;
+
+public enum Language {
+ FRENCH("french"), ENGLISH("english"), ITALIAN("italian"), SPANISH("spanish"), GERMAN("german");
+ private final String language;
+
+ Language(String language) {
+ this.language = language;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/MusicHub.java b/src/main/java/musichub/business/MusicHub.java
new file mode 100644
index 0000000..8db2f11
--- /dev/null
+++ b/src/main/java/musichub/business/MusicHub.java
@@ -0,0 +1,405 @@
+package musichub.business;
+
+import musichub.util.XMLHandler;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.UnsupportedAudioFileException;
+import java.io.IOException;
+import java.util.*;
+
+class SortByDate implements Comparator<Album> {
+ public int compare(Album a1, Album a2) {
+ return a1.getDate().compareTo(a2.getDate());
+ }
+}
+
+class SortByGenre implements Comparator<Song> {
+ public int compare(Song s1, Song s2) {
+ return s1.getGenre().compareTo(s2.getGenre());
+ }
+}
+
+class SortByAuthor implements Comparator<AudioElement> {
+ public int compare(AudioElement e1, AudioElement e2) {
+ return e1.getArtist().compareTo(e2.getArtist());
+ }
+}
+
+public class MusicHub {
+ public static final String DIR = System.getProperty("user.dir");
+ public static final String ALBUMS_FILE_PATH = DIR + "/files/albums.xml";
+ public static final String PLAYLISTS_FILE_PATH = DIR + "/files/playlists.xml";
+ public static final String ELEMENTS_FILE_PATH = DIR + "/files/elements.xml";
+ private final List<Album> albums;
+ private final List<PlayList> playlists;
+ private final List<AudioElement> elements;
+ private final XMLHandler xmlHandler = new XMLHandler();
+
+ public MusicHub() {
+ albums = new LinkedList<>();
+ playlists = new LinkedList<>();
+ elements = new LinkedList<>();
+ this.loadElements();
+ this.loadAlbums();
+ this.loadPlaylists();
+ }
+
+ public void addElement(AudioElement element) {
+ elements.add(element);
+ }
+
+ public void addAlbum(Album album) {
+ albums.add(album);
+ }
+
+ public void addPlaylist(PlayList playlist) {
+ playlists.add(playlist);
+ }
+
+ public void deletePlayList(String playListTitle) throws NoPlayListFoundException {
+
+ PlayList thePlayList = null;
+ boolean result = false;
+ for (PlayList pl : playlists) {
+ if (pl.getTitle().equalsIgnoreCase(playListTitle)) {
+ thePlayList = pl;
+ break;
+ }
+ }
+
+ if (thePlayList != null)
+ result = playlists.remove(thePlayList);
+ if (!result) throw new NoPlayListFoundException("Playlist " + playListTitle + " not found!");
+ }
+
+ public Iterator<Album> albums() {
+ return albums.listIterator();
+ }
+
+ public Iterator<PlayList> playlists() {
+ return playlists.listIterator();
+ }
+
+ public Iterator<AudioElement> elements() {
+ return elements.listIterator();
+ }
+
+ public String getAlbumsTitlesSortedByDate() {
+ StringBuilder titleList = new StringBuilder();
+ albums.sort(new SortByDate());
+ for (Album al : albums)
+ titleList.append(al.getTitle()).append("\n");
+ return titleList.toString();
+ }
+
+ public String getAudiobooksTitlesSortedByAuthor() {
+ StringBuilder titleList = new StringBuilder();
+ List<AudioElement> audioBookList = new ArrayList<>();
+ for (AudioElement ae : elements)
+ if (ae instanceof AudioBook)
+ audioBookList.add(ae);
+ audioBookList.sort(new SortByAuthor());
+ for (AudioElement ab : audioBookList)
+ titleList.append(ab.getArtist()).append("\n");
+ return titleList.toString();
+ }
+
+ public List<AudioElement> getAlbumSongs(String albumTitle) throws NoAlbumFoundException {
+ Album theAlbum = null;
+ ArrayList<AudioElement> songsInAlbum = new ArrayList<>();
+ for (Album al : albums) {
+ if (al.getTitle().equalsIgnoreCase(albumTitle)) {
+ theAlbum = al;
+ break;
+ }
+ }
+ if (theAlbum == null) throw new NoAlbumFoundException("No album with this title in the MusicHub!");
+
+ List<UUID> songIDs = theAlbum.getSongs();
+ for (UUID id : songIDs)
+ for (AudioElement el : elements) {
+ if (el instanceof Song) {
+ if (el.getUUID().equals(id)) songsInAlbum.add(el);
+ }
+ }
+ return songsInAlbum;
+
+ }
+
+ public List<Song> getAlbumSongsSortedByGenre(String albumTitle) throws NoAlbumFoundException {
+ Album theAlbum = null;
+ ArrayList<Song> songsInAlbum = new ArrayList<>();
+ for (Album al : albums) {
+ if (al.getTitle().equalsIgnoreCase(albumTitle)) {
+ theAlbum = al;
+ break;
+ }
+ }
+ if (theAlbum == null) throw new NoAlbumFoundException("No album with this title in the MusicHub!");
+
+ List<UUID> songIDs = theAlbum.getSongs();
+ for (UUID id : songIDs)
+ for (AudioElement el : elements) {
+ if (el instanceof Song) {
+ if (el.getUUID().equals(id)) songsInAlbum.add((Song) el);
+ }
+ }
+ songsInAlbum.sort(new SortByGenre());
+ return songsInAlbum;
+
+ }
+
+ public void addElementToAlbum(String elementTitle, String albumTitle) throws NoAlbumFoundException, NoElementFoundException {
+ Album theAlbum = null;
+ int i;
+ boolean found = false;
+ for (i = 0; i < albums.size(); i++) {
+ if (albums.get(i).getTitle().equalsIgnoreCase(albumTitle)) {
+ theAlbum = albums.get(i);
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ AudioElement theElement = null;
+ for (AudioElement ae : elements) {
+ if (ae.getTitle().equalsIgnoreCase(elementTitle)) {
+ theElement = ae;
+ break;
+ }
+ }
+ if (theElement != null) {
+ theAlbum.addSong(theElement.getUUID());
+ //replace the album in the list
+ albums.set(i, theAlbum);
+ } else throw new NoElementFoundException("Element " + elementTitle + " not found!");
+ } else throw new NoAlbumFoundException("Album " + albumTitle + " not found!");
+
+ }
+
+ public void addElementToPlayList(String elementTitle, String playListTitle) throws NoPlayListFoundException, NoElementFoundException {
+ PlayList thePlaylist = null;
+ int i;
+ boolean found = false;
+
+ for (i = 0; i < playlists.size(); i++) {
+ if (playlists.get(i).getTitle().equalsIgnoreCase(playListTitle)) {
+ thePlaylist = playlists.get(i);
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ AudioElement theElement = null;
+ for (AudioElement ae : elements) {
+ if (ae.getTitle().equalsIgnoreCase(elementTitle)) {
+ theElement = ae;
+ break;
+ }
+ }
+ if (theElement != null) {
+ thePlaylist.addElement(theElement.getUUID());
+ //replace the album in the list
+ playlists.set(i, thePlaylist);
+ } else throw new NoElementFoundException("Element " + elementTitle + " not found!");
+
+ } else throw new NoPlayListFoundException("Playlist " + playListTitle + " not found!");
+
+ }
+
+ private void loadAlbums() {
+ NodeList albumNodes = xmlHandler.parseXMLFile(ALBUMS_FILE_PATH);
+ if (albumNodes == null) return;
+
+ for (int i = 0; i < albumNodes.getLength(); i++) {
+ if (albumNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
+ Element albumElement = (Element) albumNodes.item(i);
+ if (albumElement.getNodeName().equals("album")) {
+ try {
+ this.addAlbum(new Album(albumElement));
+ } catch (Exception ex) {
+ System.out.println("Something is wrong with the XML album element");
+ }
+ }
+ }
+ }
+ }
+
+ private void loadPlaylists() {
+ NodeList playlistNodes = xmlHandler.parseXMLFile(PLAYLISTS_FILE_PATH);
+ if (playlistNodes == null) return;
+
+ for (int i = 0; i < playlistNodes.getLength(); i++) {
+ if (playlistNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
+ Element playlistElement = (Element) playlistNodes.item(i);
+ if (playlistElement.getNodeName().equals("playlist")) {
+ try {
+ this.addPlaylist(new PlayList(playlistElement));
+ } catch (Exception ex) {
+ System.out.println("Something is wrong with the XML playlist element");
+ }
+ }
+ }
+ }
+ }
+
+ private void loadElements() {
+ NodeList audioelementsNodes = xmlHandler.parseXMLFile(ELEMENTS_FILE_PATH);
+ if (audioelementsNodes == null) return;
+
+ for (int i = 0; i < audioelementsNodes.getLength(); i++) {
+ if (audioelementsNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
+ Element audioElement = (Element) audioelementsNodes.item(i);
+ if (audioElement.getNodeName().equals("song")) {
+ try {
+ AudioElement newSong = new Song(audioElement);
+ this.addElement(newSong);
+ } catch (Exception ex) {
+ System.out.println("Something is wrong with the XML song element");
+ }
+ }
+ if (audioElement.getNodeName().equals("audiobook")) {
+ try {
+ AudioElement newAudioBook = new AudioBook(audioElement);
+ this.addElement(newAudioBook);
+ } catch (Exception ex) {
+ System.out.println("Something is wrong with the XML audiobook element");
+ }
+ }
+ }
+ }
+ }
+
+
+ public void saveAlbums() {
+ Document document = xmlHandler.createXMLDocument();
+ if (document == null) return;
+
+ // root element
+ Element root = document.createElement("albums");
+ document.appendChild(root);
+
+ //save all albums
+ for (Iterator<Album> albumsIter = this.albums(); albumsIter.hasNext(); ) {
+ Album currentAlbum = albumsIter.next();
+ currentAlbum.createXMLElement(document, root);
+ }
+ xmlHandler.createXMLFile(document, ALBUMS_FILE_PATH);
+ }
+
+ public void savePlayLists() {
+ Document document = xmlHandler.createXMLDocument();
+ if (document == null) return;
+
+ // root element
+ Element root = document.createElement("playlists");
+ document.appendChild(root);
+
+ //save all playlists
+ for (Iterator<PlayList> playlistsIter = this.playlists(); playlistsIter.hasNext(); ) {
+ PlayList currentPlayList = playlistsIter.next();
+ currentPlayList.createXMLElement(document, root);
+ }
+ xmlHandler.createXMLFile(document, PLAYLISTS_FILE_PATH);
+ }
+
+ public void saveElements() {
+ Document document = xmlHandler.createXMLDocument();
+ if (document == null) return;
+
+ // root element
+ Element root = document.createElement("elements");
+ document.appendChild(root);
+
+ //save all AudioElements
+ for (AudioElement currentElement : elements) {
+
+ if (currentElement instanceof Song) {
+ currentElement.createXMLElement(document, root);
+ }
+ if (currentElement instanceof AudioBook) {
+ currentElement.createXMLElement(document, root);
+ }
+ }
+ xmlHandler.createXMLFile(document, ELEMENTS_FILE_PATH);
+ }
+
+ public void getAudioElement(List<AudioElement> audios, String elementTitle) throws NoAlbumFoundException, UnsupportedAudioFileException, IOException, LineUnavailableException {
+ for (AudioElement el : audios) {
+ if (el.getTitle().equalsIgnoreCase(elementTitle)) {
+ el.manageAudioElement();
+ }
+ }
+
+ }
+
+ public void searchAudioElement() throws UnsupportedAudioFileException, NoAlbumFoundException, LineUnavailableException, IOException, NoElementFoundException {
+ Scanner scanner = new Scanner(System.in);
+ System.out.println("Entrez le titre ou l'artiste de la musique que vous souhaitez chercher dans la base de données");
+ String word = scanner.next().toLowerCase(Locale.ROOT);
+ List<AudioElement> searchResult = new ArrayList<>();
+ for(AudioElement el : elements){
+ if(el.getTitle().toLowerCase(Locale.ROOT).contains(word) || el.getArtist().toLowerCase(Locale.ROOT).contains(word)){
+ searchResult.add(el);
+ System.out.println(el);
+ }
+ }
+
+ if (searchResult.isEmpty()) {
+ throw new NoElementFoundException("Any result for your search");
+ }
+ if (searchResult.size() == 1) {
+ this.getAudioElement(searchResult, searchResult.get(0).getTitle());
+ }
+ }
+
+ /**
+ * Method getting a list of playlists
+ *
+ * @return a list of playlist titles
+ * @author Anthony BOULANT
+ */
+ public String getPlayListsTitles() {
+ StringBuilder titleList = new StringBuilder();
+
+ for (PlayList pl : playlists)
+ titleList.append(pl.getTitle()).append("\n");
+ return titleList.toString();
+ }
+
+ /**
+ * Method checking the songs contained in a chosen playlist and returning them if found.
+ *
+ * @param playListTitle the title of a (chosen) playlist
+ * @return a list of songs from a playlist
+ * @throws NoPlayListFoundException if the chosen playlist doesn't exist
+ * @author Anthony BOULANT
+ */
+ public List<AudioElement> getPlayListSongs(String playListTitle) throws NoPlayListFoundException {
+ PlayList thePlayList = null;
+ ArrayList<AudioElement> songsInPlayList = new ArrayList<>();
+ for (PlayList pl : playlists) {
+ if (pl.getTitle().equalsIgnoreCase(playListTitle)) {
+ thePlayList = pl;
+ break;
+ }
+ }
+ if (thePlayList == null) throw new NoPlayListFoundException("No playlist with this title in the MusicHub!");
+
+ List<UUID> songIDs = thePlayList.getElements();
+ for (UUID id : songIDs)
+ for (AudioElement el : elements) {
+ if (el instanceof Song) {
+ if (el.getUUID().equals(id)) songsInPlayList.add(el);
+ }
+ }
+ return songsInPlayList;
+
+ }
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/NoAlbumFoundException.java b/src/main/java/musichub/business/NoAlbumFoundException.java
new file mode 100644
index 0000000..04cbfcd
--- /dev/null
+++ b/src/main/java/musichub/business/NoAlbumFoundException.java
@@ -0,0 +1,8 @@
+package musichub.business;
+
+public class NoAlbumFoundException extends Exception {
+
+ public NoAlbumFoundException(String msg) {
+ super(msg);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/NoElementFoundException.java b/src/main/java/musichub/business/NoElementFoundException.java
new file mode 100644
index 0000000..a9b0d76
--- /dev/null
+++ b/src/main/java/musichub/business/NoElementFoundException.java
@@ -0,0 +1,8 @@
+package musichub.business;
+
+public class NoElementFoundException extends Exception {
+
+ public NoElementFoundException(String msg) {
+ super(msg);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/NoPlayListFoundException.java b/src/main/java/musichub/business/NoPlayListFoundException.java
new file mode 100644
index 0000000..c5eb413
--- /dev/null
+++ b/src/main/java/musichub/business/NoPlayListFoundException.java
@@ -0,0 +1,8 @@
+package musichub.business;
+
+public class NoPlayListFoundException extends Exception {
+
+ public NoPlayListFoundException(String msg) {
+ super(msg);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/PlayList.java b/src/main/java/musichub/business/PlayList.java
new file mode 100644
index 0000000..4180a62
--- /dev/null
+++ b/src/main/java/musichub/business/PlayList.java
@@ -0,0 +1,100 @@
+package musichub.business;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.ArrayList;
+import java.util.UUID;
+
+public class PlayList {
+ private final String title;
+ private final UUID uuid;
+ private ArrayList<UUID> elementUUIDs;
+
+ public PlayList(String title, String id, ArrayList<UUID> elementUUIDs) {
+ this.title = title;
+ this.uuid = UUID.fromString(id);
+ this.elementUUIDs = elementUUIDs;
+ }
+
+ public PlayList(String title) {
+ this.title = title;
+ this.uuid = UUID.randomUUID();
+ this.elementUUIDs = new ArrayList<>();
+ }
+
+ public PlayList(Element xmlElement) {
+ {
+ this.title = xmlElement.getElementsByTagName("title").item(0).getTextContent();
+
+ String uuid = null;
+ try {
+ uuid = xmlElement.getElementsByTagName("UUID").item(0).getTextContent();
+ } catch (Exception ex) {
+ System.out.println("Empty playlist UUID, will create a new one");
+ }
+ if ((uuid == null) || (uuid.isEmpty()))
+ this.uuid = UUID.randomUUID();
+ else this.uuid = UUID.fromString(uuid);
+
+ //parse list of elements:
+ Node elementsElement = xmlElement.getElementsByTagName("elements").item(0);
+ NodeList elementUUIDNodes = elementsElement.getChildNodes();
+ if (elementUUIDNodes == null) return;
+
+ this.elementUUIDs = new ArrayList<>();
+
+
+ for (int i = 0; i < elementUUIDNodes.getLength(); i++) {
+ if (elementUUIDNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
+ Element elementElement = (Element) elementUUIDNodes.item(i);
+ if (elementElement.getNodeName().equals("UUID")) {
+ try {
+ this.addElement(UUID.fromString(elementElement.getTextContent()));
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void addElement(UUID element) {
+ elementUUIDs.add(element);
+ }
+
+ public ArrayList<UUID> getElements() {
+ return elementUUIDs;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void createXMLElement(Document document, Element parentElement) {
+ Element playlistElement = document.createElement("playlist");
+ parentElement.appendChild(playlistElement);
+
+ Element nameElement = document.createElement("title");
+ nameElement.appendChild(document.createTextNode(title));
+ playlistElement.appendChild(nameElement);
+
+ Element UUIDElement = document.createElement("UUID");
+ UUIDElement.appendChild(document.createTextNode(uuid.toString()));
+ playlistElement.appendChild(UUIDElement);
+
+
+ Element elementsElement = document.createElement("elements");
+ for (UUID currentUUID : this.elementUUIDs) {
+
+ Element elementUUIDElement = document.createElement("UUID");
+ elementUUIDElement.appendChild(document.createTextNode(currentUUID.toString()));
+ elementsElement.appendChild(elementUUIDElement);
+ }
+ playlistElement.appendChild(elementsElement);
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/musichub/business/Song.java b/src/main/java/musichub/business/Song.java
new file mode 100644
index 0000000..564b7c5
--- /dev/null
+++ b/src/main/java/musichub/business/Song.java
@@ -0,0 +1,58 @@
+package musichub.business;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+public class Song extends AudioElement {
+ private Genre genre;
+
+ public Song(String title, String artist, int length, String uid, String content, String genre) {
+ super(title, artist, length, uid, content);
+ this.setGenre(genre);
+ }
+
+ public Song(String title, String artist, int length, String content, String genre) {
+ super(title, artist, length, content);
+ this.setGenre(genre);
+ }
+
+ public Song(Element xmlElement) {
+ super(xmlElement);
+ this.setGenre(xmlElement.getElementsByTagName("genre").item(0).getTextContent());
+ }
+
+ public String getGenre() {
+ return genre.getGenre();
+ }
+
+ public void setGenre(String genre) {
+ switch (genre.toLowerCase()) {
+ default -> this.genre = Genre.JAZZ;
+ case "classic" -> this.genre = Genre.CLASSIC;
+ case "hiphop" -> this.genre = Genre.HIPHOP;
+ case "rock" -> this.genre = Genre.ROCK;
+ case "pop" -> this.genre = Genre.POP;
+ case "rap" -> this.genre = Genre.RAP;
+ }
+ }
+
+ public String toString() {
+ return super.toString() + ", Genre = " + getGenre() + "\n";
+ }
+
+ public void createXMLElement(Document document, Element parentElement) {
+ // song element
+ Element song = document.createElement("song");
+
+ super.createXMLElement(document, song);
+
+ Element genreElement = document.createElement("genre");
+ genreElement.appendChild(document.createTextNode(genre.getGenre()));
+ song.appendChild(genreElement);
+
+ parentElement.appendChild(song);
+ }
+
+
+} \ No newline at end of file
diff --git a/src/main/java/musichub/main/Main.java b/src/main/java/musichub/main/Main.java
new file mode 100644
index 0000000..07786d9
--- /dev/null
+++ b/src/main/java/musichub/main/Main.java
@@ -0,0 +1,335 @@
+package musichub.main;
+
+import musichub.business.*;
+import musichub.util.LogHandler;
+
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.UnsupportedAudioFileException;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Scanner;
+
+import static musichub.util.PathValidation.isPathValid;
+import static musichub.util.Policy.showTerm;
+
+public class Main {
+ public static void main(String[] args) throws UnsupportedAudioFileException, IOException, LineUnavailableException, NoAlbumFoundException {
+
+ showTerm();
+
+ MusicHub theHub = new MusicHub();
+
+ System.out.println("Type h for available commands");
+
+
+ Scanner scan = new Scanner(System.in);
+ String choice = scan.nextLine();
+
+ String albumTitle;
+
+ if (choice.length() == 0) System.exit(0);
+
+ while (!choice.equals("")) { //if the user puts nothing, quit the loop/system
+ switch (choice.charAt(0)) {
+ case 'q': //added the option directly in the switch instead of the loop
+ System.exit(0);
+ case 'h':
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 't':
+ //album titles, ordered by date
+ System.out.println(theHub.getAlbumsTitlesSortedByDate());
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 'g':
+ //songs of an album, sorted by genre
+ System.out.println("Songs of an album sorted by genre will be displayed; enter the album name, available albums are:");
+ System.out.println(theHub.getAlbumsTitlesSortedByDate());
+
+ albumTitle = scan.nextLine();
+ try {
+ List<Song> songs = theHub.getAlbumSongsSortedByGenre(albumTitle);
+ System.out.println(songs);
+ } catch (NoAlbumFoundException ex) {
+ LogHandler.write("No album found with the requested title", "WARNING");
+ System.out.println("No album found with the requested title " + ex.getMessage());
+ }
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 'd':
+ //songs of an album
+ System.out.println("Songs of an album will be displayed; enter the album name, available albums are:");
+ System.out.println(theHub.getAlbumsTitlesSortedByDate());
+
+ albumTitle = scan.nextLine();
+ try {
+ List<AudioElement> songs = theHub.getAlbumSongs(albumTitle);
+ System.out.println(theHub.getAlbumSongs(albumTitle));
+ String song = scan.nextLine();
+ theHub.getAudioElement(songs, song);
+ } catch (NoAlbumFoundException ex) {
+ LogHandler.write("No album found with the requested title", "WARNING");
+ System.out.println("No album found with the requested title " + ex.getMessage());
+ }
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 'u':
+ //audiobooks ordered by author
+ System.out.println(theHub.getAudiobooksTitlesSortedByAuthor());
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 'c':
+ // add a new song
+ System.out.println("Enter a new song: ");
+ System.out.println("Song title: ");
+ String title = scan.nextLine();
+ System.out.println("Song genre (jazz, classic, hiphop, rock, pop, rap):");
+ String genre = scan.nextLine();
+ System.out.println("Song artist: ");
+ String artist = scan.nextLine();
+
+ int length;
+ try {
+ System.out.println("Song length in seconds: ");
+ length = Integer.parseInt(scan.nextLine());
+ } catch (NumberFormatException ex) {
+ String logMsg = "You've not provided a number for the length.";
+ LogHandler.write(logMsg, "ERROR"); //write a line in the log file
+ System.err.println(logMsg);
+ System.out.println("Type h for available commands");
+ choice = scan.nextLine();
+ break;
+ }
+
+ System.out.println("Song content: ");
+ String content = scan.nextLine();
+ if (!isPathValid(content)) {
+ String logMsg = "The music file cannot be found with the path you've provided or the extension is not .wav";
+ LogHandler.write(logMsg, "ERROR"); //write a line in the log file
+ System.err.println(logMsg);
+ System.out.println("Type h for available commands");
+ choice = scan.nextLine();
+ break;
+ }
+
+ Song s = new Song(title, artist, length, content, genre);
+ theHub.addElement(s);
+ System.out.println("New element list: ");
+ Iterator<AudioElement> it = theHub.elements();
+ while (it.hasNext()) System.out.println(it.next().getTitle());
+ LogHandler.write("Song successfully created", "INFO");
+ System.out.println("Song created!");
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 'a':
+ // add a new album
+ System.out.println("Enter a new album: ");
+ System.out.println("Album title: ");
+ String aTitle = scan.nextLine();
+ System.out.println("Album artist: ");
+ String aArtist = scan.nextLine();
+ System.out.println("Album length in seconds: ");
+ int aLength = Integer.parseInt(scan.nextLine());
+ System.out.println("Album date as YYYY-DD-MM: ");
+ String aDate = scan.nextLine();
+ Album a = new Album(aTitle, aArtist, aLength, aDate);
+ theHub.addAlbum(a);
+ System.out.println("New list of albums: ");
+ Iterator<Album> ita = theHub.albums();
+ while (ita.hasNext()) System.out.println(ita.next().getTitle());
+ LogHandler.write("Album successfully created", "INFO");
+ System.out.println("Album created!");
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case '+':
+ //add a song to an album:
+ System.out.println("Add an existing song to an existing album");
+ System.out.println("Type the name of the song you wish to add. Available songs: ");
+ Iterator<AudioElement> itae = theHub.elements();
+ while (itae.hasNext()) {
+ AudioElement ae = itae.next();
+ if (ae instanceof Song) System.out.println(ae.getTitle());
+ }
+ String songTitle = scan.nextLine();
+
+ System.out.println("Type the name of the album you wish to enrich. Available albums: ");
+ Iterator<Album> ait = theHub.albums();
+ while (ait.hasNext()) {
+ Album al = ait.next();
+ System.out.println(al.getTitle());
+ }
+ String titleAlbum = scan.nextLine();
+ try {
+ theHub.addElementToAlbum(songTitle, titleAlbum);
+ } catch (NoAlbumFoundException | NoElementFoundException ex) {
+ System.out.println(ex.getMessage());
+ }
+ LogHandler.write("Song successfully added to the album", "INFO");
+ System.out.println("Song added to the album!");
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 'l':
+ // add a new audiobook
+ System.out.println("Enter a new audiobook: ");
+ System.out.println("AudioBook title: ");
+ String bTitle = scan.nextLine();
+ System.out.println("AudioBook category (youth, novel, theater, documentary, speech)");
+ String bCategory = scan.nextLine();
+ System.out.println("AudioBook artist: ");
+ String bArtist = scan.nextLine();
+ System.out.println("AudioBook length in seconds: ");
+ int bLength = Integer.parseInt(scan.nextLine());
+ System.out.println("AudioBook content: ");
+ String bContent = scan.nextLine();
+ System.out.println("AudioBook language (french, english, italian, spanish, german)");
+ String bLanguage = scan.nextLine();
+ AudioBook b = new AudioBook(bTitle, bArtist, bLength, bContent, bLanguage, bCategory);
+ theHub.addElement(b);
+ LogHandler.write("Audiobook successfully created", "INFO");
+ System.out.println("Audiobook created! New element list: ");
+ Iterator<AudioElement> itl = theHub.elements();
+ while (itl.hasNext()) System.out.println(itl.next().getTitle());
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 'p':
+ //create a new playlist from existing elements
+ System.out.println("Add an existing song or audiobook to a new playlist");
+ System.out.println("Existing playlists:");
+ Iterator<PlayList> itpl = theHub.playlists();
+ while (itpl.hasNext()) {
+ PlayList pl = itpl.next();
+ System.out.println(pl.getTitle());
+ }
+ System.out.println("Type the name of the playlist you wish to create:");
+ String playListTitle = scan.nextLine();
+ PlayList pl = new PlayList(playListTitle);
+ theHub.addPlaylist(pl);
+ System.out.println("Available elements: ");
+
+ Iterator<AudioElement> itael = theHub.elements();
+ while (itael.hasNext()) {
+ AudioElement ae = itael.next();
+ System.out.println(ae.getTitle());
+ }
+ while (choice.charAt(0) != 'n') {
+ System.out.println("Type the name of the audio element you wish to add or 'n' to exit:");
+ String elementTitle = scan.nextLine();
+ try {
+ theHub.addElementToPlayList(elementTitle, playListTitle);
+ } catch (NoPlayListFoundException | NoElementFoundException ex) {
+ System.out.println(ex.getMessage());
+ }
+
+ System.out.println("Type y to add a new one, n to end");
+ choice = scan.nextLine();
+ }
+ LogHandler.write("Playlist successfully created", "INFO");
+ System.out.println("Playlist created!");
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case '-':
+ //delete a playlist
+ System.out.println("Delete an existing playlist. Available playlists:");
+ Iterator<PlayList> itp = theHub.playlists();
+ while (itp.hasNext()) {
+ PlayList p = itp.next();
+ System.out.println(p.getTitle());
+ }
+ String plTitle = scan.nextLine();
+ try {
+ theHub.deletePlayList(plTitle);
+ } catch (NoPlayListFoundException ex) {
+ System.out.println(ex.getMessage());
+ }
+ LogHandler.write("Playlist successfully deleted", "INFO");
+ System.out.println("Playlist deleted!");
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 's':
+ //save elements, albums, playlists
+ theHub.saveElements();
+ theHub.saveAlbums();
+ theHub.savePlayLists();
+ LogHandler.write("Elements, albums and playlists successfully saved", "INFO");
+ System.out.println("Elements, albums and playlists saved!");
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 'r':
+ //search a music
+ try {
+ theHub.searchAudioElement();
+ }
+ catch (NoElementFoundException e){
+ System.err.println(e.getMessage());
+ }
+ catch (java.io.FileNotFoundException e){
+ LogHandler.write("Please create a file with the extension .wav inside the song folder at root of the app", "ERROR");
+ System.err.println(e.getMessage() + " Please create a file with the extension .wav inside the song folder at root of the app");
+ }
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ case 'o':
+ //consult the app logs
+ LogHandler.read();
+ System.out.println("Type h for available commands");
+ choice = scan.nextLine();
+ break;
+ case 'm':
+ //songs of a playlist
+ System.out.println("Songs of a playlist will be displayed; enter the playlist name, available playlists are:");
+ System.out.println(theHub.getPlayListsTitles());
+
+ playListTitle = scan.nextLine();
+ try {
+ List<AudioElement> songs = theHub.getPlayListSongs(playListTitle);
+ System.out.println(theHub.getPlayListSongs(playListTitle));
+ String song = scan.nextLine();
+ theHub.getAudioElement(songs, song);
+ } catch (NoPlayListFoundException ex) {
+ LogHandler.write("No playlist found with the requested title", "WARNING");
+ System.out.println("No playlist found with the requested title " + ex.getMessage());
+ }
+ printAvailableCommands();
+ choice = scan.nextLine();
+ break;
+ default:
+
+ break;
+ }
+ }
+ scan.close();
+ }
+
+ private static void printAvailableCommands() {
+ System.out.println("t: display the album titles, ordered by date");
+ System.out.println("g: display songs of an album, ordered by genre");
+ System.out.println("d: display songs of an album");
+ System.out.println("u: display audiobooks ordered by author");
+ System.out.println("r: search audio elements");
+ System.out.println("c: add a new song");
+ System.out.println("a: add a new album");
+ System.out.println("+: add a song to an album");
+ System.out.println("l: add a new audiobook");
+ System.out.println("p: create a new playlist from existing songs and audio books");
+ System.out.println("m: display songs of a playlist");
+ System.out.println("-: delete an existing playlist");
+ System.out.println("s: save elements, albums, playlists");
+ System.out.println("o: consult the app logs");
+ System.out.println("q: quit program");
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/musichub/util/LogHandler.java b/src/main/java/musichub/util/LogHandler.java
new file mode 100644
index 0000000..988b149
--- /dev/null
+++ b/src/main/java/musichub/util/LogHandler.java
@@ -0,0 +1,68 @@
+package musichub.util;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.sql.Timestamp;
+
+/**
+ * Class offering a log writing method.
+ *
+ * @author Aimeric ADJUTOR
+ * @version 1.0
+ */
+
+public final class LogHandler {
+
+ /**
+ * Method that just throws an AssertionError if the class is called
+ *
+ * @throws AssertionError you can't instantiate this class
+ * @author Aimeric ADJUTOR
+ */
+
+ public LogHandler() {
+ throw new AssertionError("You just can't instantiate this class.");
+ }
+
+ /**
+ * Method that writes a log message to spoteezer.log
+ *
+ * @param msg the message to write
+ * @param type the type of log
+ * @throws IOException if the file's not there
+ */
+ public static void write(String msg, String type) throws IOException {
+
+ Timestamp timestamp = new Timestamp(System.currentTimeMillis());
+
+ //Create the log using the given message
+ String logMsg = "\n[" + timestamp + "] " + type + ": " + msg;
+
+ // Define the file name of the file
+ Path fileName = Path.of("log/spoteezer.log");
+
+ // Write into the file
+ Files.writeString(fileName, logMsg, StandardOpenOption.APPEND);
+
+
+ }
+
+ /**
+ * Method that prints the content of spoteezer.log
+ *
+ * @throws IOException if the file's not there
+ */
+ public static void read() throws IOException {
+ Path fileName = Path.of("log/spoteezer.log");
+
+ // Read the content of the file
+ String file_content = Files.readString(fileName);
+
+ // Print the content inside the file
+ System.out.println("\n" + file_content + "\n");
+
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/musichub/util/PathValidation.java b/src/main/java/musichub/util/PathValidation.java
new file mode 100644
index 0000000..ea00c24
--- /dev/null
+++ b/src/main/java/musichub/util/PathValidation.java
@@ -0,0 +1,49 @@
+package musichub.util;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Class offering a path validation method.
+ *
+ * @author Aimeric ADJUTOR
+ * @version 1.0
+ */
+
+public final class PathValidation {
+
+ /**
+ * Method that just throws an AssertionError if the class is called
+ *
+ * @throws AssertionError you can't instantiate this class
+ * @author Aimeric ADJUTOR
+ */
+
+ public PathValidation() {
+ throw new AssertionError("You just can't instantiate this class.");
+ }
+
+ /**
+ * Method that checks the validity of a given path and file.
+ *
+ * @param inputPath the path given by the user
+ * @return a boolean
+ */
+
+ public static boolean isPathValid(String inputPath) {
+ boolean isExtensionValid = false;
+
+ int index = inputPath.lastIndexOf('.');
+ if (index > 0) {
+ String extension = inputPath.substring(index + 1);
+ if (extension.equals("wav")) {
+ isExtensionValid = true;
+ }
+ }
+
+ Path path = Paths.get(inputPath);
+ return (Files.exists(path) & isExtensionValid);
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/musichub/util/Policy.java b/src/main/java/musichub/util/Policy.java
new file mode 100644
index 0000000..01c7d20
--- /dev/null
+++ b/src/main/java/musichub/util/Policy.java
@@ -0,0 +1,76 @@
+package musichub.util;
+
+import java.io.IOException;
+import java.util.Scanner;
+
+/**
+ * Class offering methods to prompt a policy agreement form to the user.
+ *
+ * @author Anthony BOULANT
+ * @version 1.0
+ */
+
+public final class Policy {
+
+ /**
+ * Method that just throws an AssertionError if the class is called
+ *
+ * @throws AssertionError you can't instantiate this class
+ * @author Anthony BOULANT
+ */
+
+ public Policy() {
+ throw new AssertionError("You just can't instantiate this class.");
+ }
+
+ /**
+ * Method prompting the whole policy agreement process
+ *
+ * @author Anthony BOULANT
+ */
+ public static void showTerm() {
+
+ String termsAndConditions = """
+ Terms and Conditions
+ In using this website you are deemed to have read and agreed to the following terms and conditions:
+ Privacy Statement
+ We are committed to protecting your privacy. Authorized employees within the company on a need to know basis only use any information collected from individual customers. We constantly review our systems and data to ensure the best possible service to our customers. Parliament has created specific offences for unauthorised actions against computer systems and data. We will investigate any such actions with a view to prosecuting and/or taking civil proceedings to recover damages against those responsible
+ These terms and conditions form part of the Agreement between the Client and ourselves. Your accessing of this website and/or undertaking of a booking or Agreement indicates your understanding, agreement to and acceptance, of the Disclaimer Notice and the full Terms and Conditions contained herein. Your statutory Consumer Rights are unaffected. s
+ © Company Name 2021 All Rights Reserved
+ """;
+
+ printAgreement();
+ Scanner scan = new Scanner(System.in);
+ String choice = scan.nextLine().toLowerCase();
+
+ while (!choice.equals("y")) {
+ switch (choice.charAt(0)) {
+ case 'n' -> System.exit(0);
+ case 'r' -> {
+ System.out.println(termsAndConditions);
+ printAgreement();
+ choice = scan.nextLine().toLowerCase();
+ }
+ default -> {
+ printAgreement();
+ choice = scan.nextLine().toLowerCase();
+ }
+ }
+ }
+ try {
+ LogHandler.write("Terms accepted by the user.", "INFO");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Method printing the commands the user can use.
+ *
+ * @author Anthony BOULANT
+ */
+ private static void printAgreement() {
+ System.out.println("By using our app, do you accept our Terms and Conditions ?");
+ System.out.println("[YES : y NO : n READ : r]");
+ }
+}
diff --git a/src/main/java/musichub/util/XMLHandler.java b/src/main/java/musichub/util/XMLHandler.java
new file mode 100644
index 0000000..4b61842
--- /dev/null
+++ b/src/main/java/musichub/util/XMLHandler.java
@@ -0,0 +1,74 @@
+package musichub.util;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.File;
+import java.io.IOException;
+
+
+public class XMLHandler {
+ TransformerFactory transformerFactory;
+ Transformer transformer;
+ DocumentBuilderFactory documentFactory;
+ DocumentBuilder documentBuilder;
+
+ public XMLHandler() {
+ try {
+ transformerFactory = TransformerFactory.newInstance();
+ transformer = transformerFactory.newTransformer();
+ documentFactory = DocumentBuilderFactory.newInstance();
+ documentBuilder = documentFactory.newDocumentBuilder();
+ } catch (TransformerException | ParserConfigurationException tfe) {
+ tfe.printStackTrace();
+ }
+ }
+
+ public void createXMLFile(Document document, String filePath) {
+ try {
+ // create the xml file
+ //transform the DOM Object to an XML File
+ DOMSource domSource = new DOMSource(document);
+ StreamResult streamResult = new StreamResult(new File(filePath));
+
+ // If you use
+ // StreamResult result = new StreamResult(System.out);
+ // the output will be pushed to the standard output ...
+ // You can use that for debugging
+
+ transformer.transform(domSource, streamResult);
+
+ } catch (TransformerException tfe) {
+ tfe.printStackTrace();
+ }
+ }
+
+ public Document createXMLDocument() {
+ return documentBuilder.newDocument();
+ }
+
+ public NodeList parseXMLFile(String filePath) {
+ NodeList elementNodes = null;
+ try {
+ Document document = documentBuilder.parse(new File(filePath));
+ Element root = document.getDocumentElement();
+
+ elementNodes = root.getChildNodes();
+ } catch (SAXException | IOException e) {
+ e.printStackTrace();
+ }
+ return elementNodes;
+ }
+
+
+} \ No newline at end of file