org.getmansky.Cache.java Source code

Java tutorial

Introduction

Here is the source code for org.getmansky.Cache.java

Source

/*
 * Copyright (C) 2015 Oleg Getmansky aka OlegusGetman
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.getmansky;

import com.google.gson.Gson;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.getmansky.model.Playlist;
import org.getmansky.model.Track;
import org.getmansky.util.EventHandler;
import org.nustaq.serialization.FSTObjectInput;
import org.nustaq.serialization.FSTObjectOutput;
import org.tritonus.share.sampled.file.TAudioFileFormat;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author OlegusGetman
 */
public class Cache {

    private final static String PLAYLISTS_PATH = "/playlists/";
    private final static String TRACKS_PATH = "/tracks/";
    private final static Logger log = Logger.getLogger(Cache.class);

    public static List<Playlist> cachedPlaylists;

    private static String getNameFromTags(File file) {
        try {
            AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(file);
            Map<?, ?> properties = ((TAudioFileFormat) fileFormat).properties();
            String title = (String) properties.get("title");
            String author = (String) properties.get("author");
            if (StringUtils.isNotBlank(title) && StringUtils.isNotBlank(author)) {
                return author + "  " + title;
            }
        } catch (UnsupportedAudioFileException | IOException ex) {
            log.fatal(ex, ex);
        }
        return null;
    }

    private static double getDuration(File file) throws UnsupportedAudioFileException, IOException {
        AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(file);
        if (fileFormat instanceof TAudioFileFormat) {
            Map<?, ?> properties = ((TAudioFileFormat) fileFormat).properties();
            String key = "duration";
            Long microseconds = (Long) properties.get(key);
            return microseconds / 1000;
        } else {
            throw new UnsupportedAudioFileException();
        }
    }

    private static void savePlaylists(List<Playlist> playlists) {
        BufferedOutputStream buf = null;
        try {
            File cacheDir = new File(Settings.storagePath + PLAYLISTS_PATH);
            if (!cacheDir.exists()) {
                cacheDir.mkdirs();
            }

            File cacheFasterFile = new File(Settings.storagePath + PLAYLISTS_PATH + "list");
            cacheFasterFile.delete();
            buf = new BufferedOutputStream(new FileOutputStream(cacheFasterFile));
            try (FSTObjectOutput output = new FSTObjectOutput(buf)) {
                output.writeObject(playlists);
                output.flush();
            }

            Gson gson = new Gson();
            String json = gson.toJson(playlists);
            FileOutputStream writer = new FileOutputStream(Settings.storagePath + PLAYLISTS_PATH + "list.json");
            writer.write(json.getBytes("UTF-8"));
            writer.close();

        } catch (FileNotFoundException ex) {
            log.log(Level.ERROR, null, ex);
        } catch (IOException ex) {
            log.log(Level.ERROR, null, ex);
        } finally {
            try {
                if (buf != null) {
                    buf.close();
                }
            } catch (IOException ex) {
                log.log(Level.ERROR, null, ex);
            }
        }
    }

    public static List<Playlist> playlists() {
        File cachedFile = new File(Settings.storagePath + PLAYLISTS_PATH + "list");
        if (cachedFile.exists()) {
            try {
                List<Playlist> playlists = null;
                try (FSTObjectInput input = new FSTObjectInput(
                        new BufferedInputStream(new FileInputStream(cachedFile)))) {
                    playlists = (List<Playlist>) input.readObject();
                    playlists = playlists.stream().sorted((pl1, pl2) -> pl1.getTitle().compareTo(pl2.getTitle()))
                            .collect(Collectors.toList());

                } catch (IOException ex) {
                    log.log(Level.ERROR, null, ex);
                    return null;
                }
                return cachedPlaylists = playlists;
            } catch (ClassNotFoundException ex) {
                return cachedPlaylists = new ArrayList<>();
            }
        } else {
            return cachedPlaylists = new ArrayList<>();
        }
    }

    public static File getContent(Track t) {
        return new File(Settings.storagePath + "/" + TRACKS_PATH + "/" + t.getId());
    }

    public static Playlist createPlaylist(String title) {
        Playlist p = new Playlist();
        p.setTitle(title);
        p.setId("offline-" + System.currentTimeMillis());
        p.setOffline(Boolean.TRUE);
        p.setTracks(new ArrayList<>());

        List<Playlist> pls = new ArrayList(playlists());
        pls.add(p);
        savePlaylists(pls);

        return p;
    }

    public static Playlist renamePlaylist(Playlist p, String title) {
        p.setTitle(title);
        List<Playlist> pls = new ArrayList(playlists());
        pls.remove(p);
        pls.add(p);
        savePlaylists(pls);
        return p;
    }

    public static void deletePlaylist(Playlist p) {
        List<Playlist> pls = new ArrayList(playlists());
        pls.remove(p);
        savePlaylists(pls);
    }

    public static Playlist pushToPlaylist(List<File> files, Playlist p, EventHandler<Track> handler) {
        List<Playlist> pls = new ArrayList(playlists());

        File fullTracksPath = new File(Settings.storagePath + "/" + TRACKS_PATH);
        fullTracksPath.mkdirs();

        files.stream().forEach((file) -> {
            Track t = new Track();
            t.setOffline(Boolean.TRUE);
            try {
                String md5 = DigestUtils.md5Hex(new FileInputStream(file));
                String newFilename = md5 + "-" + file.length() + ".mp3";
                Files.copy(file.toPath(), Paths.get(Settings.storagePath, TRACKS_PATH, newFilename),
                        StandardCopyOption.REPLACE_EXISTING);
                t.setId(newFilename);
                String nameFromTags = getNameFromTags(file);
                if (nameFromTags != null) {
                    t.setTitle(nameFromTags);
                } else {
                    t.setTitle(file.getName().substring(0, file.getName().length() - 4)); //remove ".mp3" at the end
                }
                t.setDuration(getDuration(file));
                p.getTracks().remove(t);
                p.getTracks().add(t);
                handler.handle(t);
            } catch (IOException | UnsupportedAudioFileException ex) {
                log.fatal(ex, ex);
            }
        });
        pls.remove(p);
        pls.add(p);

        savePlaylists(pls);
        return p;
    }

    public static Playlist pushToPlaylist(Track t, Playlist p) {
        List<Playlist> pls = new ArrayList(playlists());

        p.getTracks().remove(t);
        p.getTracks().add(t);
        pls.remove(p);
        pls.add(p);

        savePlaylists(pls);
        return p;
    }

    public static void renameTrack(Track t, Playlist p, String title) {
        for (Track track : p.getTracks()) {
            if (track == t) {
                t.setTitle(title);
                break;
            }
        }

        List<Playlist> playlists = playlists();
        playlists.remove(p);
        playlists.add(p);
        savePlaylists(playlists);
    }

    public static void deleteFromPlaylist(Track t, Playlist p) {
        p.getTracks().remove(t);

        List<Playlist> pls = new ArrayList(playlists());
        pls.remove(p);
        pls.add(p);
        savePlaylists(pls);
    }

    public static Integer deleteDead(Playlist p) {
        Integer cnt = 0;
        List<Track> tracks = p.getTracks();
        for (Track t : tracks) {
            if (t.getId() != null) {
                File f = new File(Settings.storagePath + "/" + TRACKS_PATH + "/" + t.getId());
                if (!f.exists()) {
                    t.setId(null);
                    cnt++;
                }
            }
        }

        for (int i = 0; i < tracks.size(); i++) {
            if (tracks.get(i).getId() == null) {
                tracks.remove(i--);
            }
        }

        List<Playlist> pls = new ArrayList(playlists());
        pls.remove(p);
        pls.add(p);
        savePlaylists(pls);
        return cnt;
    }

    public static List<Track> search(String text) {
        List<Track> totalTracks = new ArrayList();
        cachedPlaylists.stream().map(playlist -> playlist.getTracks()).forEach(tracks -> {
            totalTracks.addAll(tracks);
        });
        return totalTracks.stream().distinct()
                .filter(track -> track.getTitle().toLowerCase().contains(text.toLowerCase()))
                .collect(Collectors.toList());
    }
}