org.tinymediamanager.core.movie.entities.MovieSet.java Source code

Java tutorial

Introduction

Here is the source code for org.tinymediamanager.core.movie.entities.MovieSet.java

Source

/*
 * Copyright 2012 - 2016 Manuel Laggner
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.tinymediamanager.core.movie.entities;

import static org.tinymediamanager.core.Constants.TMDB;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.commons.lang3.StringUtils;
import org.tinymediamanager.core.ImageCache;
import org.tinymediamanager.core.MediaFileType;
import org.tinymediamanager.core.Utils;
import org.tinymediamanager.core.entities.MediaEntity;
import org.tinymediamanager.core.entities.MediaFile;
import org.tinymediamanager.core.movie.MovieList;
import org.tinymediamanager.core.movie.MovieMediaFileComparator;
import org.tinymediamanager.core.movie.MovieModuleManager;
import org.tinymediamanager.core.movie.MovieScraperMetadataConfig;
import org.tinymediamanager.core.movie.MovieSetArtworkHelper;
import org.tinymediamanager.scraper.entities.MediaArtwork;
import org.tinymediamanager.scraper.entities.MediaArtwork.MediaArtworkType;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
 * The Class MovieSet. This class is used to represent a movie set (which means a "collection" of n movies)
 * 
 * @author Manuel Laggner
 */
public class MovieSet extends MediaEntity {
    private static final Comparator<Movie> MOVIE_SET_COMPARATOR = new MovieInMovieSetComparator();
    private static final Comparator<MediaFile> MEDIA_FILE_COMPARATOR = new MovieMediaFileComparator();

    @JsonProperty
    private List<UUID> movieIds = new ArrayList<>(0);

    private List<Movie> movies = new CopyOnWriteArrayList<>();
    private String titleSortable = "";

    /**
     * Instantiates a new movieset. To initialize the propertychangesupport after loading
     */
    public MovieSet() {
        // register for dirty flag listener
        super();
    }

    public MovieSet(String title) {
        this();
        setTitle(title);

        // search for artwork
        MovieSetArtworkHelper.updateArtwork(this);
    }

    @Override
    protected Comparator<MediaFile> getMediaFileComparator() {
        return MEDIA_FILE_COMPARATOR;
    }

    @Override
    public void initializeAfterLoading() {
        super.initializeAfterLoading();

        // link with movies
        for (UUID uuid : movieIds) {
            Movie movie = MovieList.getInstance().lookupMovie(uuid);
            if (movie != null) {
                movies.add(movie);
            }
        }
    }

    @Override
    public void setTitle(String newValue) {
        super.setTitle(newValue);

        synchronized (movies) {
            for (Movie movie : movies) {
                movie.movieSetTitleChanged();
            }
        }
    }

    /**
     * Returns the sortable variant of title<br>
     * eg "The Terminator Collection" -> "Terminator Collection, The".
     * 
     * @return the title in its sortable format
     */
    public String getTitleSortable() {
        if (StringUtils.isEmpty(titleSortable)) {
            titleSortable = Utils.getSortableName(this.getTitle());
        }
        return titleSortable;
    }

    public int getTmdbId() {
        int id;
        try {
            id = (Integer) ids.get(TMDB);
        } catch (Exception e) {
            return 0;
        }
        return id;
    }

    public void setTmdbId(int newValue) {
        int oldValue = getTmdbId();
        ids.put(TMDB, newValue);
        firePropertyChange(TMDB, oldValue, newValue);
    }

    @Override
    public void setArtworkUrl(String url, MediaFileType type) {
        super.setArtworkUrl(url, type);
        MovieSetArtworkHelper.downloadArtwork(this, type);
    }

    /**
     * Sets the artwork.
     *
     * @param artwork
     *          the artwork
     * @param config
     *          the config
     */
    public void setArtwork(List<MediaArtwork> artwork, MovieScraperMetadataConfig config) {
        if (config.isArtwork()) {
            MovieSetArtworkHelper.setArtwork(this, artwork);
        }
    }

    @Override
    public String getArtworkFilename(final MediaFileType type) {
        String artworkFilename = super.getArtworkFilename(type);

        // we did not find an image - get the cached file from the url
        if (StringUtils.isBlank(artworkFilename)) {
            final String artworkUrl = getArtworkUrl(type);
            if (StringUtils.isNotBlank(artworkUrl)) {
                Path artworkFile = ImageCache.getCacheDir().resolve(ImageCache.getMD5(artworkUrl));
                if (Files.exists(artworkFile)) {
                    artworkFilename = artworkFile.toAbsolutePath().toString();
                }
            }
        }

        return artworkFilename;
    }

    /**
     * Adds the movie to the end of the list
     * 
     * @param movie
     *          the movie
     */
    public void addMovie(Movie movie) {
        synchronized (movies) {
            if (movies.contains(movie)) {
                return;
            }
            movies.add(movie);
            movieIds.add(movie.getDbId());

            // update artwork
            MovieSetArtworkHelper.updateArtwork(this);

            saveToDb();
        }

        // write images
        List<Movie> movies = new ArrayList<>(1);
        movies.add(movie);
        if (MovieModuleManager.MOVIE_SETTINGS.isEnableMovieSetArtworkMovieFolder()) {
            MovieSetArtworkHelper.writeImagesToMovieFolder(this, movies);
        }

        firePropertyChange("addedMovie", null, movie);
        firePropertyChange("movies", null, movies);
    }

    /**
     * Inserts the movie into the right position of the list
     * 
     * @param movie
     *          the movie to insert into the movie set
     */
    public void insertMovie(Movie movie) {
        synchronized (movies) {
            if (movies.contains(movie)) {
                return;
            }

            int index = Collections.binarySearch(movies, movie, MOVIE_SET_COMPARATOR);
            if (index < 0) {
                movies.add(-index - 1, movie);
                movieIds.add(-index - 1, movie.getDbId());
            } else if (index >= 0) {
                movies.add(index, movie);
                movieIds.add(index, movie.getDbId());
            }

            // update artwork
            MovieSetArtworkHelper.updateArtwork(this);

            saveToDb();
        }

        // write images
        List<Movie> movies = new ArrayList<>(1);
        movies.add(movie);
        if (MovieModuleManager.MOVIE_SETTINGS.isEnableMovieSetArtworkMovieFolder()) {
            MovieSetArtworkHelper.writeImagesToMovieFolder(this, movies);
        }

        firePropertyChange("addedMovie", null, movie);
        firePropertyChange("movies", null, movies);
    }

    /**
     * Removes the movie from the list.
     * 
     * @param movie
     *          the movie
     */
    public void removeMovie(Movie movie) {
        // remove images from movie folder
        Path imageFile = movie.getPathNIO().resolve("movieset-fanart.jpg");
        if (Files.exists(imageFile)) {
            Utils.deleteFileSafely(imageFile);
        }
        imageFile = movie.getPathNIO().resolve("movieset-poster.jpg");
        if (Files.exists(imageFile)) {
            Utils.deleteFileSafely(imageFile);
        }
        if (movie.getMovieSet() != null) {
            movie.setMovieSet(null);
            movie.saveToDb();
        }

        synchronized (movies) {
            movies.remove(movie);
            movieIds.remove(movie.getDbId());

            // update artwork
            MovieSetArtworkHelper.updateArtwork(this);

            saveToDb();
        }

        firePropertyChange("movies", null, movies);
        firePropertyChange("removedMovie", null, movie);
    }

    public List<Movie> getMovies() {
        return movies;
    }

    /**
     * Sort movies inside this movie set by using either the sort title, release date or year.
     */
    public void sortMovies() {
        synchronized (movies) {
            Utils.sortList(movies, MOVIE_SET_COMPARATOR);
            // rebuild the ID table the same way
            movieIds.clear();
            for (Movie movie : movies) {
                movieIds.add(movie.getDbId());
            }
        }
        firePropertyChange("movies", null, movies);
    }

    /**
     * Removes the all movies from this movie set.
     */
    public void removeAllMovies() {
        // store all old movies to remove the nodes in the tree
        List<Movie> oldValue = new ArrayList<>(movies);
        // remove images from movie folder
        synchronized (movies) {
            for (Movie movie : movies) {
                Path imageFile = movie.getPathNIO().resolve("movieset-fanart.jpg");
                if (Files.exists(imageFile)) {
                    Utils.deleteFileSafely(imageFile);
                }
                imageFile = movie.getPathNIO().resolve("movieset-poster.jpg");
                if (Files.exists(imageFile)) {
                    Utils.deleteFileSafely(imageFile);
                }

                if (movie.getMovieSet() != null) {
                    movie.setMovieSet(null);
                    movie.writeNFO();
                    movie.saveToDb();
                }
            }
            movies.clear();
            movieIds.clear();

            // update artwork
            MovieSetArtworkHelper.updateArtwork(this);

            saveToDb();
        }

        firePropertyChange("movies", null, movies);
        firePropertyChange("removedAllMovies", oldValue, movies);
    }

    /**
     * toString. used for JComboBox in movie editor
     * 
     * @return the string
     */
    @Override
    public String toString() {
        return getTitle();
    }

    public int getMovieIndex(Movie movie) {
        return movies.indexOf(movie);
    }

    public void rewriteAllImages() {
        List<MediaFileType> types = Arrays.asList(MediaFileType.POSTER, MediaFileType.FANART, MediaFileType.BANNER,
                MediaFileType.LOGO, MediaFileType.CLEARLOGO, MediaFileType.CLEARART);

        for (MediaFileType type : types) {
            MovieSetArtworkHelper.downloadArtwork(this, type);
        }
    }

    public Boolean getHasImages() {
        if (!StringUtils.isEmpty(getArtworkFilename(MediaFileType.POSTER))
                && !StringUtils.isEmpty(getArtworkFilename(MediaFileType.FANART))) {
            return true;
        }
        return false;
    }

    public List<Path> getImagesToCache() {
        // get files to cache
        List<Path> filesToCache = new ArrayList<>();

        if (StringUtils.isNotBlank(getArtworkFilename(MediaFileType.POSTER))) {
            filesToCache.add(Paths.get(getArtworkFilename(MediaFileType.POSTER)));
        }

        if (StringUtils.isNotBlank(getArtworkFilename(MediaFileType.FANART))) {
            filesToCache.add(Paths.get(getArtworkFilename(MediaFileType.FANART)));
        }

        return filesToCache;
    }

    @Override
    public synchronized void callbackForWrittenArtwork(MediaArtworkType type) {
    }

    @Override
    public void saveToDb() {
        MovieList.getInstance().persistMovieSet(this);
    }

    @Override
    public void deleteFromDb() {
        MovieList.getInstance().removeMovieSetFromDb(this);
    }

    /**
     * clean movies from this movieset if there are any inconsistances
     */
    public void cleanMovieSet() {
        MovieList movieList = MovieList.getInstance();
        boolean dirty = false;

        for (Movie movie : new ArrayList<>(movies)) {
            if (!movieList.getMovies().contains(movie)) {
                movies.remove(movie);
                movieIds.remove(movie.getDbId());
                dirty = true;
            }
        }

        if (dirty) {
            saveToDb();
        }
    }

    /*******************************************************************************
     * helper classses
     *******************************************************************************/
    private static class MovieInMovieSetComparator implements Comparator<Movie> {
        @Override
        public int compare(Movie o1, Movie o2) {
            if (o1 == null || o2 == null) {
                return 0;
            }

            // sort with release date if available
            if (o1.getReleaseDate() != null && o2.getReleaseDate() != null) {
                return o1.getReleaseDate().compareTo(o2.getReleaseDate());
            }

            // sort with year if available
            if (StringUtils.isNotBlank(o1.getYear()) && StringUtils.isNotBlank(o2.getYear())) {
                try {
                    int year1 = Integer.parseInt(o1.getYear());
                    int year2 = Integer.parseInt(o2.getYear());
                    return year1 - year2;
                } catch (Exception ignored) {
                }
            }

            // fallback
            return 0;
        }
    }
}