From e64ffae239b19871704b4ac1e9cd58275ed58622 Mon Sep 17 00:00:00 2001
From: Clyhtsuriva <aimeric@adjutor.xyz>
Date: Sat, 26 Jun 2021 12:34:26 +0200
Subject: Changed the architecture to respect maven and generated an empty
 javadoc

---
 src/main/java/musichub/business/Album.java         | 145 +++++++++
 src/main/java/musichub/business/AudioBook.java     |  78 +++++
 src/main/java/musichub/business/AudioElement.java  |  88 ++++++
 src/main/java/musichub/business/Category.java      |  14 +
 src/main/java/musichub/business/Genre.java         |  14 +
 src/main/java/musichub/business/Language.java      |  14 +
 src/main/java/musichub/business/MusicHub.java      | 329 +++++++++++++++++++++
 .../musichub/business/NoAlbumFoundException.java   |   8 +
 .../musichub/business/NoElementFoundException.java |   8 +
 .../business/NoPlayListFoundException.java         |   8 +
 src/main/java/musichub/business/PlayList.java      | 100 +++++++
 src/main/java/musichub/business/Song.java          |  56 ++++
 src/main/java/musichub/main/Main.java              | 248 ++++++++++++++++
 src/main/java/musichub/util/XMLHandler.java        |  74 +++++
 14 files changed, 1184 insertions(+)
 create mode 100644 src/main/java/musichub/business/Album.java
 create mode 100644 src/main/java/musichub/business/AudioBook.java
 create mode 100644 src/main/java/musichub/business/AudioElement.java
 create mode 100644 src/main/java/musichub/business/Category.java
 create mode 100644 src/main/java/musichub/business/Genre.java
 create mode 100644 src/main/java/musichub/business/Language.java
 create mode 100644 src/main/java/musichub/business/MusicHub.java
 create mode 100644 src/main/java/musichub/business/NoAlbumFoundException.java
 create mode 100644 src/main/java/musichub/business/NoElementFoundException.java
 create mode 100644 src/main/java/musichub/business/NoPlayListFoundException.java
 create mode 100644 src/main/java/musichub/business/PlayList.java
 create mode 100644 src/main/java/musichub/business/Song.java
 create mode 100644 src/main/java/musichub/main/Main.java
 create mode 100644 src/main/java/musichub/util/XMLHandler.java

(limited to 'src/main')

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..e0a686b
--- /dev/null
+++ b/src/main/java/musichub/business/AudioElement.java
@@ -0,0 +1,88 @@
+package musichub.business;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+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);
+
+    }
+
+}
\ 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..38e2214
--- /dev/null
+++ b/src/main/java/musichub/business/MusicHub.java
@@ -0,0 +1,329 @@
+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 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);
+    }
+}
\ 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..3e9011b
--- /dev/null
+++ b/src/main/java/musichub/business/Song.java
@@ -0,0 +1,56 @@
+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..b72a95b
--- /dev/null
+++ b/src/main/java/musichub/main/Main.java
@@ -0,0 +1,248 @@
+package musichub.main;
+
+import musichub.business.*;
+
+import java.util.Iterator;
+import java.util.Scanner;
+
+public class Main {
+    public static void main(String[] args) {
+
+        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 {
+                        System.out.println(theHub.getAlbumSongsSortedByGenre(albumTitle));
+                    } catch (NoAlbumFoundException ex) {
+                        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 {
+                        System.out.println(theHub.getAlbumSongs(albumTitle));
+                    } catch (NoAlbumFoundException ex) {
+                        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();
+                    System.out.println("Song length in seconds: ");
+                    int length = Integer.parseInt(scan.nextLine());
+                    System.out.println("Song content: ");
+                    String content = scan.nextLine();
+                    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());
+                    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());
+                    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());
+                    }
+                    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);
+                    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();
+                    }
+                    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());
+                    }
+                    System.out.println("Playlist deleted!");
+                    printAvailableCommands();
+                    choice = scan.nextLine();
+                    break;
+                case 's':
+                    //save elements, albums, playlists
+                    theHub.saveElements();
+                    theHub.saveAlbums();
+                    theHub.savePlayLists();
+                    System.out.println("Elements, albums and playlists saved!");
+                    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("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("-: delete an existing playlist");
+        System.out.println("s: save elements, albums, playlists");
+        System.out.println("q: quit program");
+    }
+}
\ No newline at end of file
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
-- 
cgit v1.2.3