• Album.java

  • §
    package MusicLandscape.entities;
  • §

    Concrete implementation of the abstract class Release.

    This was mostly a tedious implementation of a linked list. Normally it is better to use a Java built-in class like java.util.ArrayList.

    /**
     * This class represents an album as a concrete release of a specific artist.<br>
     * An album has a list of tracks, which, in this class, is implemented as a (singly) linked lists of tracks.
     *
     * @author Jonas Altrock (ew20b126@technikum-wien.at)
     * @version 1
     * @since ExerciseSheet04
     */
    public class Album extends Release {
        /**
         * A single item of a linked list of tracks.<br>
         * A single list item consists of the primary data, in our case a track, and a reference to its successor,
         * which is another list item.
         */
        private static class TrackListItem {
            /**
             * A reference to the next item in the list.
             */
            TrackListItem next;
    
            /**
             * The primary data of this list item.
             */
            Track track;
    
            /**
             * Creates a list item from a track.<br>
             * Simply wraps a list item around a track, so it can be inserted into a linked list of tracks.
             * <p>
             * This list item does NOT maintain its own copy of the original track. It means a track in the list can be
             * modified from the caller who might still maintain a reference, however, the list structure is protected.
             *
             * @param t the track of this list item
             */
            public TrackListItem(Track t) {
                track = t;
            }
        }
    
        /**
         * The tracks of this album.<br>
         * More specifically this is the head of the linked list of tracks of this album.
         */
        private TrackListItem trackListHead;
    
        /**
         * Creates a default Album.<br>
         * A default album is a default release with an empty track list.
         */
        public Album() {
        }
    
        /**
         * Creates a copy of an album.<br>
         * All release parts of this album are copied as described in the release copy constructor.
         * <p>
         * The track list of this album contains (references to) the same tracks as the original, meaning tracks are not
         * deeply copied.
         *
         * @param orig the album to copy
         */
        public Album(Album orig) {
            super(orig);
            TrackListItem it = orig.trackListHead;
    
            if (it == null) {
                return;
            }
    
            trackListHead = new TrackListItem(it.track);
    
            while (it.next != null) {
                trackListHead.next = new TrackListItem(it.next.track);
                it = it.next;
            }
        }
    
        /**
         * Create an album with a specific title of a specific artist in a specific year.
         *
         * @param title  the title of the new album
         * @param artist the artist of the new album
         * @param year   the year of the new album
         */
        public Album(String title, Artist artist, int year) {
            super(title, artist, year);
        }
  • §

    addTrack()

  • §
        /**
         * Adds a track to the list of tracks.<br>
         * Tracks are added to the end of the list.
         * <p>
         * Null tracks are not accepted. The method returns whether the list was modified.
         * true means success (track was added) false means no success (track was NOT added).
         *
         * @param t the track to add
         * @return whether the list was modified (added successfully) or not
         */
        public boolean addTrack(Track t) {
            if (t == null) {
                return false;
            }
  • §

    no head = create new list

            if (trackListHead == null) {
                trackListHead = new TrackListItem(t);
                return true;
            }
  • §

    iterate to end

            TrackListItem tail = trackListHead;
    
            while (tail.next != null) {
                tail = tail.next;
            }
  • §

    append new list item

            tail.next = new TrackListItem(t);
            return true;
        }
  • §

    removeTrack()

  • §
        /**
         * Removes a track from the track from the list of tracks.
         * <p>
         * Removes and returns the track at position n from the list of tracks. Element numbering starts at 0, such that in
         * a list containing a single element the position of that element is 0 (zero). If the requested element does not
         * exist in the list null is returned.
         *
         * @param n the (zero-based) position of the track to be removed.
         * @return the removed track or null
         */
        public Track removeTrack(int n) {
            int i = 0;
            TrackListItem it = trackListHead;
            Track t;
  • §

    empty list

            if (it == null) {
                return null;
            }
  • §

    remove head

            if (n == i) {
                t = it.track;
                trackListHead = it.next;
                return t;
            }
  • §

    find predecessor of n

            while (it != null && i < (n - 1)) {
                i++;
                it = it.next;
            }
  • §

    has no successor = element at index n does not exist

            if (it == null || it.next == null) {
                return null;
            }
  • §

    remove element n

            t = it.next.track;
            it.next = it.next.next;
    
            return t;
        }
    
        /**
         * Gets the number of tracks on this album.
         *
         * @return the number of tracks
         */
        public int nrTracks() {
            int n = 0;
            TrackListItem it = trackListHead;
    
            while (it != null) {
                n += 1;
                it = it.next;
            }
    
            return n;
        }
    
        /**
         * Gets the tracks of this album.
         * <p>
         * This method creates an array containing all tracks of this album preserving their current order. If the album
         * has no tracks, an array of size zero is returned. The tracks in the returned array are NOT (deep) copies of the
         * tracks currently maintained by this album, meaning that the caller can modify the tracks of this album, however
         * modification of their ordering in the list is not possible from outside.
         *
         * @return the tracks of this album in order
         */
        public Track[] getTracks() {
            Track[] tracks = new Track[nrTracks()];
            int i = 0;
            TrackListItem it = trackListHead;
    
            while (it != null) {
                tracks[i] = it.track;
                i += 1;
                it = it.next;
            }
    
            return tracks;
        }
  • §

    totalTime()

  • §
        /**
         * Gets the total running time of this album.
         * <p>
         * The running time is the sum of the running times of all tracks in this album. The time is returned in seconds.
         *
         * @return the total running time in seconds.
         */
        public int totalTime() {
            int i = 0;
            int time = 0;
            TrackListItem it = trackListHead;
    
            while (it != null) {
                time += it.track.getDuration();
                i += 1;
                it = it.next;
            }
    
            return time;
        }
    
        /**
         * Gets a String representation of this album.
         * <p>
         * The String representation of an album adds the titles of all tracks to the release String representation.
         * The list of track names is enclosed by opening and closing brackets ([,]).
         * Track titles are also enclosed by opening and closing brackets.
         *
         * @return the string representation
         */
        public String toString() {
            StringBuilder sb = new StringBuilder("[");
            TrackListItem it = trackListHead;
    
            while (it != null) {
                sb.append("[").append(it.track.getTitle()).append("]");
                it = it.next;
            }
    
            sb.append("]");
    
            return super.toString() + "\n" + sb;
        }
    }