com.moviejukebox.model.Movie Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yamj Show documentation
Show all versions of yamj Show documentation
Static analysis of MovieJukebox project
/*
* Copyright (c) 2004-2012 YAMJ Members
* http://code.google.com/p/moviejukebox/people/list
*
* Web: http://code.google.com/p/moviejukebox/
*
* This software is licensed under a Creative Commons License
* See this page: http://code.google.com/p/moviejukebox/wiki/License
*
* For any reuse or distribution, you must make clear to others the
* license terms of this work.
*/
package com.moviejukebox.model;
import com.moviejukebox.model.Artwork.Artwork;
import com.moviejukebox.model.Artwork.ArtworkType;
import com.moviejukebox.plugin.MovieDatabasePlugin;
import com.moviejukebox.tools.*;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.pojava.datetime.DateTime;
/**
* Movie bean
*
* @author jjulien
* @author artem.gratchev
*/
@XmlType
public class Movie implements Comparable, Identifiable, IMovieBasicInformation {
/*
* Static & Final variables that are used for control and don't relate
* specifically to the Movie object
*/
private static final Logger logger = Logger.getLogger(Movie.class);
public static final String UNKNOWN = "UNKNOWN";
public static final String NOTRATED = "Not Rated";
public static final String REMOVE = "Remove"; // All Movie objects with this type will be removed from library before index generation
public static final String TYPE_MOVIE = "MOVIE";
public static final String TYPE_TVSHOW = "TVSHOW";
public static final String TYPE_UNKNOWN = UNKNOWN;
public static final String TYPE_VIDEO_UNKNOWN = UNKNOWN;
public static final String TYPE_VIDEO_HD = "HD";
public static final String TYPE_BLURAY = "BLURAY"; // Used to indicate what physical format the video is
public static final String TYPE_DVD = "DVD"; // Used to indicate what physical format the video is
public static final String TYPE_FILE = "FILE"; // Used to indicate what physical format the video is
public static final String TYPE_PERSON = "PERSON";
public static final String SPACE_SLASH_SPACE = " / ";
private String mjbVersion = UNKNOWN;
private String mjbRevision = UNKNOWN;
private DateTime mjbGenerationDate = null;
/*
* --------------------------------------------------------------------------------
* Properties that control the object
*/
private static final List SORT_IGNORE_PREFIXES = new ArrayList();
private int highdef720 = PropertiesUtil.getIntProperty("highdef.720.width", "1280"); // Get the minimum width for a high-definition movies
private int highdef1080 = PropertiesUtil.getIntProperty("highdef.1080.width", "1920"); // Get the minimum width for a high-definition movies
private String[] ratingSource = PropertiesUtil.getProperty("mjb.rating.source", "average").split(",");
private String tmpRatingIgnore = PropertiesUtil.getProperty("mjb.rating.ignore", "");
private List ratingIgnore = StringTools.isValidString(tmpRatingIgnore) ? Arrays.asList(tmpRatingIgnore.split(",")) : new ArrayList();
private static final Set GENRE_SKIP_LIST = new HashSet(); // List of genres to ignore
private static String titleSortType = PropertiesUtil.getProperty("mjb.sortTitle", "title");
/*
* --------------------------------------------------------------------------------
* Properties related to the Movie object itself
*/
private String baseName; // Safe name for generated files
private String baseFilename; // Base name for finding posters, nfos, banners, etc.
private Map idMap = new HashMap(2);
private String title = UNKNOWN;
private String titleSort = UNKNOWN;
private String strippedTitleSort = UNKNOWN; // Not saved, used to speedup the sort
private String originalTitle = UNKNOWN;
private String year = UNKNOWN;
private String releaseDate = UNKNOWN;
private Map ratings = new HashMap();
private String plot = UNKNOWN;
private String outline = UNKNOWN;
private String quote = UNKNOWN;
private String tagline = UNKNOWN;
private String country = UNKNOWN;
private String company = UNKNOWN;
private String runtime = UNKNOWN;
private String language = UNKNOWN;
private String videoType = UNKNOWN;
private String subtitles = UNKNOWN;
private Set directors = new LinkedHashSet();
private Map sets = new HashMap();
private Collection genres = new TreeSet();
private Set cast = new LinkedHashSet();
private Set writers = new LinkedHashSet();
private String container = UNKNOWN; // AVI, MKV, TS, etc.
private Set codecs = new LinkedHashSet();
private String resolution = UNKNOWN; // 1280x528
private String aspect = UNKNOWN;
private String videoSource = UNKNOWN;
private String videoOutput = UNKNOWN;
private float fps = 60;
private String certification = UNKNOWN;
private String showStatus = UNKNOWN; // For TV shows a status such as "Continuing" or "Ended"
private boolean scrapeLibrary;
private boolean extra = Boolean.FALSE; // TODO Move extra flag to movie file
private boolean trailerExchange = Boolean.FALSE; // Trailers
private long trailerLastScan = 0; // Trailers
private Collection awards = new ArrayList(); // Issue 1901: Awards
private Collection people = new ArrayList(); // Issue 1897: Cast enhancement
private String budget = UNKNOWN; // Issue 2012: Financial information about movie
private Map openweek = new HashMap();
private Map gross = new HashMap();
private List didYouKnow = new ArrayList(); // Issue 2013: Add trivia
private String libraryPath = UNKNOWN;
private String movieType = TYPE_MOVIE;
private String formatType = TYPE_FILE;
private boolean overrideTitle = Boolean.FALSE;
private boolean overrideYear = Boolean.FALSE;
private int top250 = -1;
private String libraryDescription = UNKNOWN;
private long prebuf = -1;
// Graphics URLs & files
private Set artwork = new LinkedHashSet();
private String posterURL = UNKNOWN; // The original, unaltered, poster
private String posterFilename = UNKNOWN; // The poster filename
private String detailPosterFilename = UNKNOWN; // The resized poster for skins
private String thumbnailFilename = UNKNOWN; // The thumbnail version of the poster for skins
private List footerFilename = new ArrayList(); // The footer image for skins
private String fanartURL = UNKNOWN; // The fanart URL
private String fanartFilename = UNKNOWN; // The resized fanart file
private String bannerURL = UNKNOWN; // The TV Show banner URL
private String bannerFilename = UNKNOWN; // The resized banner file
private String clearArtURL = UNKNOWN;
private String clearArtFilename = UNKNOWN;
private String clearLogoURL = UNKNOWN;
private String clearLogoFilename = UNKNOWN;
private String seasonThumbURL = UNKNOWN;
private String seasonThumbFilename = UNKNOWN;
private String tvThumbURL = UNKNOWN;
private String tvThumbFilename = UNKNOWN;
private String movieDiscURL = UNKNOWN;
private String movieDiscFilename = UNKNOWN;
// File information
private Date fileDate = null;
private long fileSize = 0;
private long lastModifiedTimeStamp = Long.valueOf(0); // cache value
private boolean watchedFile = Boolean.FALSE; // Watched / Unwatched - Set from the .watched files
private boolean watchedNFO = Boolean.FALSE; // Watched / Unwatched - Set from the NFO file
// Navigation data
private String first = UNKNOWN;
private String previous = UNKNOWN;
private String next = UNKNOWN;
private String last = UNKNOWN;
private Map indexes = new HashMap();
// Media file properties
private Collection movieFiles = new TreeSet();
private Collection extraFiles = new TreeSet();
private Set dirtyFlags = EnumSet.noneOf(DirtyFlag.class); // List of the dirty flags associated with the Movie
private File file;
private File containerFile;
// Set information
private boolean isSetMaster = Boolean.FALSE; // True if movie actually is only a entry point to movies set.
private int setSize = 0; // Amount of movies in set
private MovieDatabasePlugin movieScanner = null;
/*
* --------------------------------------------------------------------------------
* End of properties
* --------------------------------------------------------------------------------
*/
static {
if (GENRE_SKIP_LIST.isEmpty()) {
StringTokenizer st = new StringTokenizer(PropertiesUtil.getProperty("mjb.genre.skip", ""), ",;|");
while (st.hasMoreTokens()) {
GENRE_SKIP_LIST.add(st.nextToken().toLowerCase());
}
}
}
public void setMjbVersion(String mjbVersion) {
if (StringTools.isNotValidString(mjbVersion)) {
this.mjbVersion = SystemTools.getVersion();
} else {
this.mjbVersion = mjbVersion;
}
}
@XmlElement
public String getMjbVersion() {
return mjbVersion;
}
public void setMjbRevision(String mjbRevision) {
if (StringTools.isNotValidString(mjbRevision)) {
this.mjbRevision = "0000";
} else {
this.mjbRevision = mjbRevision;
}
}
@XmlElement
public String getMjbRevision() {
// If YAMJ is self compiled then the revision information may not exist.
if (!(StringUtils.isBlank(mjbRevision) || (mjbRevision.equalsIgnoreCase("${env.SVN_REVISION}")))) {
return mjbRevision;
} else {
return Movie.UNKNOWN;
}
}
public void setMjbGenerationDateString(String mjbGenerationDate) {
try {
this.mjbGenerationDate = DateTime.parse(mjbGenerationDate);
} catch (Exception error) {
this.mjbGenerationDate = new DateTime();
}
}
public void setMjbGenerationDate(DateTime mjbGenerationDate) {
if (mjbGenerationDate == null) {
this.mjbGenerationDate = new DateTime();
} else {
this.mjbGenerationDate = mjbGenerationDate;
}
}
@XmlElement
public String getMjbGenerationDateString() {
return getMjbGenerationDate().toString(StringTools.getDateFormatLongString());
}
public DateTime getMjbGenerationDate() {
if (this.mjbGenerationDate == null) {
this.mjbGenerationDate = new DateTime();
}
return this.mjbGenerationDate;
}
public void addGenre(String genre) {
if (StringTools.isValidString(genre) && !extra && !GENRE_SKIP_LIST.contains(genre.toLowerCase())) {
setDirty(DirtyFlag.INFO);
//logger.debug("Genre added: " + genre);
genres.add(genre);
}
}
public void addGenres(List genres) {
for (String newGenre : genres) {
addGenre(newGenre);
}
}
public void addSet(String set) {
addSet(set, null);
}
public void addSet(String set, Integer order) {
if (StringTools.isValidString(set)) {
setDirty(DirtyFlag.INFO);
logger.debug("Set added: " + set + ", order: " + order);
sets.put(set, order);
}
}
public void addMovieFile(MovieFile movieFile) {
if (movieFile != null) {
setDirty(DirtyFlag.INFO);
// Always replace MovieFile
for (MovieFile mf : this.movieFiles) {
if (mf.compareTo(movieFile) == 0) {
movieFile.setFile(mf.getFile());
movieFile.setInfo(mf.getInfo());
}
}
//logger.debug("Movie addMovieFile: " + movieFile.getFilename());
this.movieFiles.remove(movieFile);
this.movieFiles.add(movieFile);
}
}
public void addAward(AwardEvent award) {
if (award != null) {
setDirty(DirtyFlag.INFO);
this.awards.add(award);
}
}
public void addPerson(Filmography person) {
if (person != null) {
boolean duplicate = Boolean.FALSE;
String name = person.getName();
String job = person.getJob();
for (Filmography p : people) {
if (p.getName().equals(name) && p.getJob().equals(job)) {
duplicate = Boolean.TRUE;
break;
}
}
if (!duplicate) {
setDirty(DirtyFlag.INFO);
people.add(person);
}
}
}
public void removePerson(Filmography person) {
if (person != null) {
people.remove(person);
}
}
public void addPerson(String name) {
addPerson(Movie.UNKNOWN, name, Movie.UNKNOWN, Movie.UNKNOWN, Movie.UNKNOWN, Movie.UNKNOWN);
}
public void addPerson(String key, String name) {
addPerson(key, name, Movie.UNKNOWN, Movie.UNKNOWN, Movie.UNKNOWN, Movie.UNKNOWN);
}
public void addPerson(String key, String name, String url) {
addPerson(key, name, url, Movie.UNKNOWN, Movie.UNKNOWN, Movie.UNKNOWN);
}
public void addPerson(String key, String name, String url, String job) {
addPerson(key, name, url, job, Movie.UNKNOWN, Movie.UNKNOWN);
}
public void addPerson(String key, String name, String url, String job, String character) {
addPerson(key, name, url, job, character, Movie.UNKNOWN);
}
public void addPerson(String key, String name, String url, String job, String character, String doublage) {
if (StringUtils.isNotBlank(name)
&& StringUtils.isNotBlank(key)
&& StringUtils.isNotBlank(url)
&& StringUtils.isNotBlank(job)) {
Filmography person = new Filmography();
if (key.indexOf(':') > -1) {
String[] keys = key.split(":");
person.setId(keys[0], keys[1]);
} else {
person.setId(key);
}
if (name.indexOf(':') > -1) {
String[] names = name.split(":");
if (StringTools.isValidString(names[0])) {
person.setName(names[0]);
person.setTitle(names[1]);
} else if (StringTools.isValidString(names[1])) {
person.setName(names[1]);
} else {
person.setName(name);
}
} else {
person.setName(name);
}
person.setUrl(url);
person.setCharacter(character);
person.setDoublage(doublage);
person.setJob(job);
person.setDepartment();
int countActor = 0;
if (person.getDepartment().equalsIgnoreCase(Filmography.DEPT_ACTORS)) {
for (Filmography member : people) {
if (member.getDepartment().equalsIgnoreCase(Filmography.DEPT_ACTORS)) {
countActor++;
}
}
}
person.setOrder(countActor);
person.setCastId(people.size());
person.setScrapeLibrary(scrapeLibrary);
addPerson(person);
}
}
public void removeMovieFile(MovieFile movieFile) {
if (movieFile != null) {
setDirty(DirtyFlag.INFO);
for (MovieFile mf : this.movieFiles) {
if (mf.compareTo(movieFile) == 0) {
this.movieFiles.remove(mf);
break;
}
}
}
}
public boolean hasNewMovieFiles() {
for (MovieFile movieFile : movieFiles) {
if (movieFile.isNewFile()) {
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}
/**
* Add a new extra file to the movie
*
* @param extraFile
*/
public void addExtraFile(ExtraFile extraFile) {
addExtraFile(extraFile, Boolean.TRUE);
}
/**
* Add a new extra file to the movie without marking the movie as dirty.
*
* @param extraFile
* @param isNewFile Use carefully as this will not cause the movie to be
* marked as dirty and may not be written out
*/
public void addExtraFile(ExtraFile extraFile, boolean isNewFile) {
// Only add extraFile if it doesn't already exists
if (extraFile != null && !this.extraFiles.contains(extraFile)) {
if (isNewFile) {
setDirty(DirtyFlag.INFO);
}
this.extraFiles.add(extraFile);
}
}
public boolean hasNewExtraFiles() {
for (MovieFile movieFile : extraFiles) {
if (movieFile.isNewFile()) {
return Boolean.TRUE;
}
}
return Boolean.FALSE;
}
public String getStrippedTitleSort() {
// If we have a strippedTitleSort, return that
if (StringTools.isValidString(strippedTitleSort)) {
return strippedTitleSort;
}
StringBuilder text = new StringBuilder(getStrippedTitle(getTitleSort()));
int season = getSeason();
// Added season to handle properly sorting the season numbers
if (season >= 0) {
if (season < 10) {
text.append(" 0");
} else {
text.append(" ");
}
text.append(season);
}
// Added Year to handle movies like Ocean's Eleven (1960) and Ocean's Eleven (2001)
text.append(" (").append(this.getYear()).append(") ");
strippedTitleSort = text.toString();
return strippedTitleSort;
}
/**
* Remove the sorting strip prefix from the title
*
* @param title
* @return
*/
private String getStrippedTitle(String title) {
String lowerTitle = title.toLowerCase();
for (String prefix : SORT_IGNORE_PREFIXES) {
if (lowerTitle.startsWith(prefix.toLowerCase())) {
return new String(title.substring(prefix.length()));
}
}
return title;
}
@Override
public int compareTo(Movie anotherMovie) {
return this.getStrippedTitleSort().compareToIgnoreCase(anotherMovie.getStrippedTitleSort());
}
@Deprecated
public String getAudioCodec() {
StringBuilder sb = new StringBuilder();
boolean firstCodec = Boolean.TRUE;
for (Codec audioCodec : codecs) {
if (audioCodec.getCodecType() == CodecType.AUDIO) {
if (firstCodec) {
firstCodec = Boolean.FALSE;
} else {
sb.append(SPACE_SLASH_SPACE);
}
if (StringTools.isValidString(audioCodec.getCodecIdHint())) {
sb.append(audioCodec.getCodecIdHint());
} else if (StringTools.isValidString(audioCodec.getCodec())) {
sb.append(audioCodec.getCodec());
} else if (StringTools.isValidString(audioCodec.getCodecFormat())) {
sb.append(audioCodec.getCodecFormat());
} else if (StringTools.isValidString(audioCodec.getCodecId())) {
sb.append(audioCodec.getCodecId());
} else {
sb.append(Movie.UNKNOWN);
}
if (StringTools.isValidString(audioCodec.getCodecLanguage())) {
sb.append(" (");
sb.append(audioCodec.getCodecLanguage());
sb.append(")");
}
}
}
if (sb.length() > 0) {
return sb.toString();
} else {
return UNKNOWN;
}
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.IMovieBasicInformation#getBaseName()
*/
@Override
public String getBaseName() {
return baseName;
}
public String getBaseFilename() {
return baseFilename;
}
@XmlElementWrapper(name = "cast")
@XmlElement(name = "actor")
public Collection getCast() {
return cast;
}
@XmlElementWrapper(name = "writers")
@XmlElement(name = "writer")
public Collection getWriters() {
return writers;
}
public Collection getDidYouKnow() {
return didYouKnow;
}
public String getCompany() {
return company;
}
public String getContainer() {
return container;
}
public String getCountry() {
return country;
}
public Collection getFiles() {
return movieFiles;
}
@XmlElementWrapper(name = "extras")
@XmlElement(name = "extra")
public Collection getExtraFiles() {
return extraFiles;
}
@XmlElementWrapper(name = "awards")
@XmlElement(name = "award")
public Collection getAwards() {
return awards;
}
@XmlElementWrapper(name = "people")
@XmlElement(name = "person")
public Collection getPeople() {
return people;
}
public Collection getPerson(String department) {
Collection pList = new ArrayList();
for (Filmography p : people) {
if (p.getDepartment().equals(department)) {
pList.add(p.getTitle());
}
}
return pList;
}
public String getCertification() {
return certification;
}
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getFirst() {
return first;
}
/**
* Get the first logical file of the set of videos
*
* @return
*/
public MovieFile getFirstFile() {
for (MovieFile part : movieFiles) {
if (part.getFirstPart() == 1) {
return part;
}
}
Iterator i = movieFiles.iterator();
if (i.hasNext()) {
return i.next();
} else {
return null;
}
}
public float getFps() {
return fps;
}
@XmlElementWrapper(name = "genres")
@XmlElement(name = "genre")
public Collection getGenres() {
return genres;
}
public Collection getSetsKeys() {
return sets.keySet();
}
public Integer getSetOrder(String set) {
return sets.get(set);
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.Identifiable#getId(java.lang.String)
*/
@Override
public String getId(String key) {
String result = idMap.get(key);
if (result != null) {
return result;
} else {
return UNKNOWN;
}
}
public Map getIdMap() {
return idMap;
}
public String getGross(String country) {
String result = gross.get(country);
if (result != null) {
return result;
} else {
return UNKNOWN;
}
}
public Map getGross() {
return gross;
}
public String getOpenWeek(String country) {
String result = openweek.get(country);
if (result != null) {
return result;
} else {
return UNKNOWN;
}
}
public Map getOpenWeek() {
return openweek;
}
public static class MovieId {
@XmlAttribute
public String movieDatabase;
@XmlValue
public String value;
}
@XmlElement(name = "id")
public List getMovieIds() {
List list = new ArrayList();
for (Entry e : idMap.entrySet()) {
MovieId id = new MovieId();
id.movieDatabase = e.getKey();
id.value = e.getValue();
list.add(id);
}
return list;
}
public void setMovieIds(List list) {
idMap.clear();
for (MovieId id : list) {
idMap.put(id.movieDatabase, id.value);
}
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.IMovieBasicInformation#getLanguage()
*/
@Override
public String getLanguage() {
return language;
}
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getLast() {
return last;
}
@XmlElementWrapper(name = "files")
@XmlElement(name = "file")
public Collection getMovieFiles() {
return movieFiles;
}
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getNext() {
return next;
}
public String getPlot() {
return plot;
}
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getPrevious() {
return previous;
}
public String getReleaseDate() {
return releaseDate;
}
public String getResolution() {
return resolution;
}
// Return the width of the movie
public int getWidth() {
int width;
try {
width = Integer.parseInt(new String(getResolution().substring(0, getResolution().indexOf("x"))));
} catch (Exception error) {
// This will catch the exception if mediainfo is not installed.
width = 0;
}
return width;
}
public String getRuntime() {
return runtime;
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.IMovieBasicInformation#getSeason()
*/
@Override
public int getSeason() {
/*
* Return the first season as the whole season
*
* This could be changed later to allow multi season movie objects. Do
* not return a value for the set master.
*/
if (movieFiles.size() > 0 && !isSetMaster) {
return getFirstFile().getSeason();
} else {
// Strictly speaking this isn't "-1" its a non-existent season.
return -1;
}
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.IMovieBasicInformation#getTitle()
*/
@Override
public String getTitle() {
return title;
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.IMovieBasicInformation#getTitleSort()
*/
/**
* Return the correct sort title based on the mjb.sortTitle parameter
*/
@Override
public String getTitleSort() {
// If we have a titleSort, return that
if (StringTools.isValidString(titleSort)) {
return titleSort;
}
// There are three choices for the sort title: title, original, filename
if ("title".equalsIgnoreCase(titleSortType)) {
// Set the title sort (so this is only done once)
setTitleSort(title);
return titleSort;
}
if ("filename".equalsIgnoreCase(titleSortType)) {
// Set the title sort (so this is only done once)
setTitleSort(baseName);
return titleSort;
}
if ("original".equalsIgnoreCase(titleSortType)) {
if (StringTools.isValidString(originalTitle)) {
// Set the title sort (so this is only done once)
setTitleSort(originalTitle);
return titleSort;
} else {
setTitleSort(title);
return titleSort;
}
}
// Set the title sort (so this is only done once)
setTitleSort(title);
return titleSort;
}
@Override
public String getOriginalTitle() {
return originalTitle;
}
public String getVideoOutput() {
return videoOutput;
}
public String getVideoSource() {
return videoSource;
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.IMovieBasicInformation#getYear()
*/
@Override
public String getYear() {
return year;
}
public String getBudget() {
return budget;
}
public String getSubtitles() {
return subtitles;
}
public void setDirty(DirtyFlag dirtyType, boolean dirty) {
if (dirty) {
dirtyFlags.add(dirtyType);
} else {
dirtyFlags.remove(dirtyType);
}
}
public void setDirty(DirtyFlag dirtyType) {
dirtyFlags.add(dirtyType);
}
/**
* Clear ALL the dirty flags, and just set DirtyFlag.INFO to the passed
* value
*
* @param dirty
*/
public void setDirty(boolean dirty) {
clearDirty();
setDirty(DirtyFlag.INFO, dirty);
}
/**
* Returns true if ANY of the dirty flags are set. Use with caution, it's
* better to test individual flags as you need them, rather than this
* generic flag
*
* @return
*/
public boolean isDirty() {
if (dirtyFlags.isEmpty()) {
return Boolean.FALSE;
} else {
return Boolean.TRUE;
}
}
public String showDirty() {
if (dirtyFlags.isEmpty()) {
return "NOT DIRTY";
} else {
return dirtyFlags.toString();
}
}
public Set getDirty() {
return dirtyFlags;
}
public void clearDirty() {
dirtyFlags.clear();
}
public boolean isDirty(DirtyFlag dirtyType) {
return dirtyFlags.contains(dirtyType);
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.IMovieBasicInformation#isTVShow()
*/
@XmlAttribute(name = "isTV")
@Override
public boolean isTVShow() {
return (this.movieType.equals(TYPE_TVSHOW) || getSeason() != -1);
}
@XmlTransient
public boolean isBluray() {
return this.formatType.equals(TYPE_BLURAY);
}
@XmlTransient
public boolean isDVD() {
return this.formatType.equals(TYPE_DVD);
}
@XmlTransient
public boolean isFile() {
return this.formatType.equals(TYPE_FILE);
}
@XmlTransient
public boolean isHD() {
// Depreciated this check in favour of the width check
// return this.videoType.equals(TYPE_VIDEO_HD) || videoOutput.indexOf("720") != -1 || videoOutput.indexOf("1080") != -1;
return (getWidth() >= highdef720);
}
@XmlTransient
public boolean isHD1080() {
return (getWidth() >= highdef1080);
}
@XmlTransient
public boolean is3D() {
return (getVideoSource().indexOf("3D") > -1);
}
public void setBaseName(String baseName) {
this.baseName = validateString(baseName, this.baseName);
}
public void setBaseFilename(String baseFilename) {
this.baseFilename = validateString(baseFilename, this.baseFilename);
}
public void addDidYouKnow(String fact) {
if (fact != null && !didYouKnow.contains(fact)) {
setDirty(DirtyFlag.INFO);
didYouKnow.add(fact);
}
}
public void setDidYouKnow(List facts) {
if (facts != null && !facts.isEmpty()) {
didYouKnow = facts;
setDirty(DirtyFlag.INFO);
}
}
public void clearDidYouKnow() {
didYouKnow.clear();
setDirty(DirtyFlag.INFO);
}
public void clearAwards() {
awards.clear();
setDirty(DirtyFlag.INFO);
}
public void addActor(String actor) {
if (StringTools.isNotValidString(actor)) {
return;
}
if (!cast.contains(actor.trim())) {
setDirty(DirtyFlag.INFO);
cast.add(actor.trim());
}
}
public void addActor(String actorKey, String actorName, String character, String actorUrl, String doublage) {
if (actorName != null) {
String name = actorName;
if (actorName.indexOf(':') > -1) {
String[] names = actorName.split(":");
if (StringTools.isValidString(names[1])) {
name = names[1];
} else if (StringTools.isValidString(names[0])) {
name = names[0];
}
}
name = name.trim();
boolean found = Boolean.FALSE;
for (Filmography p : people) {
if (p.getName().equalsIgnoreCase(name) && p.getDepartment().equals(Filmography.DEPT_ACTORS)) {
found = Boolean.TRUE;
break;
}
}
if (!found) {
addActor(name);
addPerson(actorKey, actorName, actorUrl, StringUtils.capitalize(Filmography.JOB_ACTOR), character, doublage);
}
}
}
public void setCast(Collection cast) {
if (cast != null && !cast.isEmpty()) {
clearCast();
this.cast.addAll(cast);
Collection pList = new ArrayList();
for (Filmography p : people) {
if (p.getDepartment().equals(Filmography.DEPT_ACTORS)) {
pList.add(p);
}
}
for (Filmography p : pList) {
removePerson(p);
}
for (String member : cast) {
addActor(Movie.UNKNOWN, member, Movie.UNKNOWN, Movie.UNKNOWN, Movie.UNKNOWN);
}
}
}
public void clearCast() {
setDirty(DirtyFlag.INFO);
cast.clear();
}
public void addWriter(String writer) {
if (writer != null && !writers.contains(writer)) {
setDirty(DirtyFlag.INFO);
writers.add(writer);
}
}
public void addWriter(String writerKey, String writerName, String writerUrl) {
if (writerName != null) {
String name = writerName;
if (writerName.contains(":")) {
String[] names = writerName.split(":");
if (StringTools.isValidString(names[1])) {
name = names[1];
} else if (StringTools.isValidString(names[0])) {
name = names[0];
}
}
name = name.trim();
boolean found = Boolean.FALSE;
for (Filmography p : people) {
if (p.getName().equalsIgnoreCase(name) && p.getDepartment().equals(Filmography.DEPT_WRITING)) {
found = Boolean.TRUE;
break;
}
}
if (!found) {
addWriter(name);
addPerson(writerKey, writerName, writerUrl, "Writer");
}
}
}
public void setWriters(Collection writers) {
if (writers != null && !writers.isEmpty()) {
clearWriters();
this.writers.addAll(writers);
Collection pList = new ArrayList();
for (Filmography p : people) {
if (p.getDepartment().equals(Filmography.DEPT_WRITING)) {
pList.add(p);
}
}
for (Filmography p : pList) {
removePerson(p);
}
for (String member : writers) {
addWriter(Movie.UNKNOWN, member, Movie.UNKNOWN);
}
}
}
public void clearWriters() {
setDirty(DirtyFlag.INFO);
writers.clear();
}
public void setCompany(String company) {
this.company = validateString(company, this.company);
}
public void setContainer(String container) {
this.container = validateString(container, this.container);
}
public void setCountry(String country) {
this.country = validateString(country, this.country);
}
/**
* Get just one director from the collection
*
* @return
*/
public String getDirector() {
if (directors != null && !directors.isEmpty()) {
return directors.iterator().next();
} else {
return UNKNOWN;
}
}
public Collection getDirectors() {
return directors;
}
public void setDirectors(Collection directors) {
if (directors != null && !directors.isEmpty()) {
clearDirectors();
this.directors.addAll(directors);
Collection pList = new ArrayList();
for (Filmography p : people) {
if (p.getDepartment().equals(Filmography.DEPT_DIRECTING)) {
pList.add(p);
}
}
for (Filmography p : pList) {
removePerson(p);
}
for (String member : directors) {
addDirector(Movie.UNKNOWN, member, Movie.UNKNOWN);
}
}
}
public void clearDirectors() {
setDirty(DirtyFlag.INFO);
directors.clear();
}
public void addDirector(String director) {
if (director != null && !directors.contains(director)) {
setDirty(DirtyFlag.INFO);
directors.add(director);
}
}
public void addDirector(String key, String name, String URL) {
if (name != null) {
String directorName = name;
if (name.contains(":")) {
String[] names = name.split(":");
if (StringTools.isValidString(names[1])) {
directorName = names[1];
} else if (StringTools.isValidString(names[0])) {
directorName = names[0];
}
}
directorName = directorName.trim();
boolean found = Boolean.FALSE;
for (Filmography p : people) {
if (p.getName().equalsIgnoreCase(directorName) && p.getDepartment().equals(Filmography.DEPT_DIRECTING)) {
found = Boolean.TRUE;
break;
}
}
if (!found) {
addDirector(directorName);
addPerson(key, name, URL, "Director");
}
}
}
public void setFirst(String first) {
this.first = validateString(first, this.first);
}
public void setFps(float fps) {
//Prevent wrong result caused by floating point rounding by allowing difference of 0.1 fpsS
if (Math.abs(fps - this.fps) > 0.1) {
setDirty(DirtyFlag.INFO);
this.fps = fps;
}
}
public void setGenres(Collection genresToAdd) {
if (!extra) {
// Only check if the skip list isn't empty
if (!GENRE_SKIP_LIST.isEmpty()) {
// remove any unwanted genres from the new collection
Collection genresFinal = new TreeSet();
Iterator genreIterator = genresToAdd.iterator();
while (genreIterator.hasNext()) {
String genreToAdd = genreIterator.next();
if (!GENRE_SKIP_LIST.contains(genreToAdd.toLowerCase())) {
genresFinal.add(genreToAdd);
}
}
// Add the trimmed genre list
this.genres = genresFinal;
} else {
// No need to remove genres, so add them all
this.genres = genresToAdd;
}
setDirty(DirtyFlag.INFO);
}
}
public void setSets(Map sets) {
setDirty(DirtyFlag.INFO);
this.sets = sets;
}
public Map getSets() {
return sets;
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.Identifiable#setId(java.lang.String,
* java.lang.String)
*/
@Override
public void setId(String key, String id) {
if (StringTools.isValidString(key) && StringTools.isValidString(id) && !id.equalsIgnoreCase(this.getId(key))) {
setDirty(DirtyFlag.INFO);
this.idMap.put(key, id);
}
}
public void setId(String key, int id) {
setId(key, Integer.toString(id));
}
public void setGross(String country, String value) {
if (StringTools.isValidString(country) && StringTools.isValidString(value) && !value.equalsIgnoreCase(this.getGross(country))) {
setDirty(DirtyFlag.INFO);
this.gross.put(country, value);
}
}
public void setGross(Map gross) {
if (gross != null) {
this.gross = gross;
}
}
public void setOpenWeek(String country, String value) {
if (StringTools.isValidString(country) && StringTools.isValidString(value) && !value.equalsIgnoreCase(this.getOpenWeek(country))) {
setDirty(DirtyFlag.INFO);
this.openweek.put(country, value);
}
}
public void setOpenWeek(Map openweek) {
if (openweek != null) {
this.openweek = openweek;
}
}
public void setLanguage(String language) {
this.language = validateString(language, this.language);
}
public void setCertification(String certification) {
this.certification = validateString(certification, this.certification);
}
public void setLast(String last) {
this.last = validateString(last, this.last);
}
public void setMovieFiles(Collection movieFiles) {
setDirty(DirtyFlag.INFO);
this.movieFiles = movieFiles;
}
public void setExtraFiles(Collection extraFiles) {
setDirty(DirtyFlag.INFO);
this.extraFiles = extraFiles;
}
public void setAwards(Collection awards) {
setDirty(DirtyFlag.INFO);
this.awards = awards;
}
public void setPeople(Collection people) {
setDirty(DirtyFlag.INFO);
this.people = people;
}
public void setNext(String next) {
this.next = validateString(next, this.next);
}
public void setPlot(String plot) {
this.plot = validateString(plot, this.plot);
}
public String getOutline() {
return outline;
}
public void setOutline(String outline) {
this.outline = validateString(outline, this.outline);
}
public void setPrevious(String previous) {
this.previous = validateString(previous, this.previous);
}
public int getRating() {
if (ratings == null || ratings.isEmpty()) {
return -1;
}
for (String site : ratingSource) {
if ("average".equalsIgnoreCase(site)) {
// Return the average of the ratings
int rating = 0;
int count = 0;
for (String ratingSite : ratings.keySet()) {
if (ratingIgnore.size() > 0) {
if (ratingIgnore.contains(ratingSite)) {
continue;
} else {
boolean found = Boolean.FALSE;
for (String ignoreName : ratingIgnore) {
if (ratingSite.indexOf(ignoreName) == 0) {
found = Boolean.TRUE;
break;
}
}
if (found) {
continue;
}
}
}
rating += ratings.get(ratingSite);
count++;
}
return (count > 0 ? (rating / count) : 0);
}
if (ratings.containsKey(site)) {
return ratings.get(site);
}
}
// No ratings found, so return -1
return -1;
}
public int getRating(String site) {
if (ratings.containsKey(site)) {
return ratings.get(site);
} else {
return -1;
}
}
public Map getRatings() {
return ratings;
}
public void addRating(String site, int rating) {
if (StringTools.isValidString(site)) {
if (ratings.containsKey(site)) {
if (ratings.get(site) != rating) {
ratings.remove(site);
ratings.put(site, rating);
setDirty(DirtyFlag.INFO);
}
} else {
ratings.put(site, rating);
}
}
}
public void setRatings(Map ratings) {
if (ratings != null && !ratings.isEmpty()) {
this.ratings = ratings;
}
}
public void setReleaseDate(String releaseDate) {
this.releaseDate = validateString(releaseDate, this.releaseDate);
}
public void setResolution(String resolution) {
this.resolution = validateString(resolution, this.resolution);
}
public void setResolution(String width, String height) {
if (StringTools.isValidString(width) && StringTools.isValidString(height)) {
setResolution(width + "x" + height);
}
}
public void setRuntime(String runtime) {
if (StringUtils.isBlank(runtime)) {
this.runtime = UNKNOWN;
return;
}
if (!runtime.equalsIgnoreCase(this.runtime)) {
setDirty(DirtyFlag.INFO);
// Escape the first "0" AlloCine gives sometimes
if (runtime.startsWith("0")) {
this.runtime = new String(runtime.substring(1)).trim();
} else {
this.runtime = runtime.trim();
}
}
}
public void setSubtitles(String subtitles) {
this.subtitles = validateString(subtitles, this.subtitles);
}
public void setTitle(String name) {
String newName;
if (StringUtils.isBlank(name)) {
newName = UNKNOWN;
} else {
newName = name;
}
if (!newName.equals(this.title)) {
setDirty(DirtyFlag.INFO);
this.title = newName;
// If we don't have a original title, then use the title
if (StringTools.isNotValidString(originalTitle)) {
setOriginalTitle(newName);
}
}
}
public void setTitleSort(String title) {
String newTitle;
if (StringUtils.isBlank(title)) {
newTitle = UNKNOWN;
} else {
newTitle = title;
}
if (!newTitle.equals(this.titleSort)) {
int idx = 0;
while (idx < newTitle.length() && !Character.isLetterOrDigit(newTitle.charAt(idx))) {
idx++;
}
// Issue 1908: Replace all non-standard characters in the title sort
this.titleSort = StringTools.stringMapReplacement(new String(newTitle.substring(idx)));
setDirty(DirtyFlag.INFO);
}
}
public void setOriginalTitle(String originalTitle) {
this.originalTitle = validateString(originalTitle, this.originalTitle);
}
/**
* Get the video codec. You should use the getCodec methods instead
*
* @return
* @deprecated
*/
@Deprecated
public String getVideoCodec() {
for (Codec videoCodec : codecs) {
if (videoCodec.getCodecType() == CodecType.VIDEO) {
if (StringTools.isValidString(videoCodec.getCodecIdHint())) {
return videoCodec.getCodecIdHint();
}
if (StringTools.isValidString(videoCodec.getCodec())) {
return videoCodec.getCodec();
}
if (StringTools.isValidString(videoCodec.getCodecFormat())) {
return videoCodec.getCodecFormat();
}
if (StringTools.isValidString(videoCodec.getCodecId())) {
return videoCodec.getCodecId();
}
}
}
return UNKNOWN;
}
public void setVideoOutput(String videoOutput) {
this.videoOutput = validateString(videoOutput, this.videoOutput);
}
public void setVideoSource(String videoSource) {
this.videoSource = validateString(videoSource, this.videoSource);
}
public void setYear(String year) {
this.year = validateString(year, this.year);
}
public void setBudget(String budget) {
this.budget = validateString(budget, this.budget);
}
public String getQuote() {
return quote;
}
public void setQuote(String quote) {
this.quote = validateString(quote, this.quote);
}
/**
* Validate the testString to ensure it is correct before setting the Dirty
* INFO flag if it is different
*
* @param testString
* @param currentString
* @return
*/
private String validateString(String testString, String currentString) {
String newString;
if (StringUtils.isBlank(testString)) {
newString = UNKNOWN;
} else {
newString = testString;
}
if (!newString.equalsIgnoreCase(currentString)) {
setDirty(DirtyFlag.INFO);
}
return newString;
}
@XmlTransient
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
@XmlTransient
public File getContainerFile() {
return containerFile;
}
public void setContainerFile(File containerFile) {
this.containerFile = containerFile;
}
public long getLastModifiedTimestamp() {
if (!isSetMaster()) {
synchronized (this) {
if (lastModifiedTimeStamp == 0L) {
for (MovieFile mf : getMovieFiles()) {
lastModifiedTimeStamp = Math.max(lastModifiedTimeStamp, mf.getLastModified());
}
}
//make sure the fileDate is correct too
addFileDate(new Date(lastModifiedTimeStamp));
return lastModifiedTimeStamp;
}
} else {
// Sets don't hold the time/date of their files, so just return the time of the file
return getFileDate().getTime();
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[Movie ");
for (Map.Entry e : idMap.entrySet()) {
sb.append("[id_").append(e.getKey()).append("=").append(e.getValue()).append("]");
}
sb.append("[title=").append(title).append("]");
sb.append("[titleSort=").append(titleSort).append("]");
sb.append("[year=").append(year).append("]");
sb.append("[releaseDate=").append(releaseDate).append("]");
sb.append("[ratings=").append(ratings).append("]");
sb.append("[top250=").append(top250).append("]");
sb.append("[posterURL=").append(posterURL).append("]");
sb.append("[bannerURL=").append(bannerURL).append("]");
sb.append("[fanartURL=").append(fanartURL).append("]");
sb.append("[plot=").append(plot).append("]");
sb.append("[outline=").append(outline).append("]");
sb.append("[director=").append(directors.toString()).append("]");
sb.append("[country=").append(country).append("]");
sb.append("[company=").append(company).append("]");
sb.append("[runtime=").append(runtime).append("]");
sb.append("[season=").append(getSeason()).append("]");
sb.append("[language=").append(language).append("]");
sb.append("[subtitles=").append(subtitles).append("]");
sb.append("[container=").append(container).append("]"); // AVI, MKV, TS, etc.
sb.append("[codecs=").append(codecs.toString()).append("]");
sb.append("[resolution=").append(resolution).append("]"); // 1280x528
sb.append("[videoSource=").append(videoSource).append("]");
sb.append("[videoOutput=").append(videoOutput).append("]");
sb.append("[fps=").append(fps).append("]");
sb.append("[certification=").append(certification).append("]");
sb.append("[cast=").append(cast).append("]");
sb.append("[writers=").append(writers).append("]");
sb.append("[genres=").append(genres).append("]");
sb.append("[libraryDescription=").append(libraryDescription).append("]");
sb.append("[prebuf=").append(prebuf).append("]");
sb.append("]");
return sb.toString();
}
/**
* Sets the "extra" flag to mark this file as an extra. Will trigger the
* "dirty" setting too
*
* @param extra Boolean flag, true=extra file, false=normal file
*/
public void setExtra(boolean extra) {
setDirty(DirtyFlag.INFO);
this.extra = extra;
if (extra) {
genres.clear();
}
}
/**
* This function will return true if the movie can have trailers.
*
* @param movie
* @return
*/
public boolean canHaveTrailers() {
if (isExtra() || getMovieType().equals(Movie.TYPE_TVSHOW)) {
return Boolean.FALSE;
} else {
return Boolean.TRUE;
}
}
public void setTrailerExchange(Boolean trailerExchange) {
if (this.trailerExchange != trailerExchange) {
setDirty(DirtyFlag.INFO);
this.trailerExchange = trailerExchange;
}
}
/**
* Set the date of the last trailers scan
*
* @param lastScan date of the last trailers scan
*/
public void setTrailerLastScan(String lastScan) {
try {
SimpleDateFormat sdf = StringTools.getDateFormat();
setTrailerLastScan(sdf.parse(lastScan).getTime());
} catch (Exception error) {
setTrailerLastScan(0);
}
}
/**
* Set the date of the last trailers scan
*
* @param lastScan date of the last trailers scan (milliseconds offset from
* the Epoch)
*/
public void setTrailerLastScan(long lastScan) {
if (lastScan != this.trailerLastScan) {
setDirty(DirtyFlag.INFO);
this.trailerLastScan = lastScan;
}
}
/**
* Get the date of the last trailers scan
*
* @return the date of the last trailers scan (milliseconds offset from the
* Epoch)
*/
public long getTrailerLastScan() {
return trailerLastScan;
}
/**
* @return Boolean flag indicating if this file is an extra
*/
@XmlAttribute(name = "isExtra")
public boolean isExtra() {
return extra;
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.IMovieBasicInformation#isTrailerExchange()
*/
@XmlJavaTypeAdapter(BooleanYesNoAdapter.class)
@Override
public Boolean isTrailerExchange() {
return trailerExchange;
}
public void setMovieType(String movieType) {
this.movieType = validateString(movieType, this.movieType);
}
public String getMovieType() {
return this.movieType;
}
public void setFormatType(String formatType) {
this.formatType = validateString(formatType, this.formatType);
}
public String getFormatType() {
return this.formatType;
}
public void setVideoType(String videoType) {
this.videoType = validateString(videoType, this.videoType);
}
public String getVideoType() {
return this.videoType;
}
public String getLibraryPath() {
return libraryPath;
}
public void setLibraryPath(String libraryPath) {
this.libraryPath = libraryPath;
}
@Deprecated
public String getAudioChannels() {
StringBuilder sb = new StringBuilder();
boolean firstChannel = Boolean.TRUE;
for (Codec codec : codecs) {
if (codec.getCodecType().equals(CodecType.AUDIO)) {
if (firstChannel) {
firstChannel = Boolean.FALSE;
} else {
sb.append(SPACE_SLASH_SPACE);
}
sb.append(codec.getCodecChannels());
}
}
return sb.toString();
}
@XmlTransient
public boolean isOverrideTitle() {
return overrideTitle;
}
public void setOverrideTitle(boolean overrideTitle) {
this.overrideTitle = overrideTitle;
}
public int getTop250() {
return top250;
}
public void setTop250(int top250) {
if (top250 != this.top250) {
setDirty(DirtyFlag.INFO);
this.top250 = top250;
}
}
public String getLibraryDescription() {
return libraryDescription;
}
public void setLibraryDescription(String libraryDescription) {
this.libraryDescription = validateString(libraryDescription, this.libraryDescription);
}
public long getPrebuf() {
return prebuf;
}
public void setPrebuf(long prebuf) {
this.prebuf = prebuf;
}
@XmlTransient
public boolean isScrapeLibrary() {
return scrapeLibrary;
}
public void setScrapeLibrary(boolean scrapeLibrary) {
this.scrapeLibrary = scrapeLibrary;
}
public static void addSortIgnorePrefixes(String prefix) {
SORT_IGNORE_PREFIXES.add(prefix);
}
/**
* Take the passed DTO and update the movie information
*
* @param dto
*/
public void mergeFileNameDTO(MovieFileNameDTO dto) {
setTitle(dto.getTitle());
setExtra(dto.isExtra());
Codec tempCodec;
if (StringTools.isValidString(dto.getAudioCodec())) {
tempCodec = new Codec(CodecType.AUDIO);
tempCodec.setCodec(dto.getAudioCodec());
tempCodec.setCodecSource(CodecSource.FILENAME);
addCodec(tempCodec);
}
if (StringTools.isValidString(dto.getVideoCodec())) {
tempCodec = new Codec(CodecType.VIDEO);
tempCodec.setCodec(dto.getVideoCodec());
tempCodec.setCodecSource(CodecSource.FILENAME);
addCodec(tempCodec);
}
setVideoSource(dto.getVideoSource());
setContainer(dto.getContainer());
setFps(dto.getFps() > 0 ? dto.getFps() : 60);
setMovieIds(dto.getMovieIds());
if (dto.getSeason() > -1) {
// Mark the movie as a TV Show
setMovieType(Movie.TYPE_TVSHOW);
}
for (MovieFileNameDTO.SetDTO set : dto.getSets()) {
addSet(set.getTitle(), set.getIndex() >= 0 ? set.getIndex() : null);
}
setYear(dto.getYear() > 0 ? String.valueOf(dto.getYear()) : null);
setLanguage(dto.getLanguages().size() > 0 ? dto.getLanguages().get(0) : null);
if (dto.getHdResolution() != null) {
setVideoType(TYPE_VIDEO_HD);
// Check if the videoOutput is UNKNOWN and clear it if it is
if (StringTools.isNotValidString(videoOutput)) {
videoOutput = "";
}
switch (dto.getFps()) {
case 23:
videoOutput = "1080p 23.976Hz";
break;
case 24:
videoOutput = "1080p 24Hz";
break;
case 25:
videoOutput = "1080p 25Hz";
break;
case 29:
videoOutput = "1080p 29.97Hz";
break;
case 30:
videoOutput = "1080p 30Hz";
break;
case 50:
if (StringUtils.isNotBlank(videoOutput)) {
videoOutput += " ";
}
videoOutput += "50Hz";
break;
case 59:
videoOutput = "1080p 59.94Hz";
break;
case 60:
if (StringUtils.isNotBlank(videoOutput)) {
videoOutput += " ";
}
videoOutput += "60Hz";
break;
default:
if (StringUtils.isBlank(videoOutput)) {
videoOutput = Movie.UNKNOWN;
} else {
videoOutput += " 60Hz";
}
}
} else {
switch (dto.getFps()) {
case 23:
videoOutput = "23p";
break;
case 24:
videoOutput = "24p";
break;
case 29:
case 30:
case 60:
videoOutput = "NTSC";
break;
case 25:
case 49:
case 50:
videoOutput = "PAL";
break;
default:
videoOutput = Movie.UNKNOWN;
break;
}
}
}
/*
* (non-Javadoc)
*
* @see com.moviejukebox.model.IMovieBasicInformation#isSetMaster()
*/
@XmlAttribute(name = "isSet")
@Override
public boolean isSetMaster() {
return isSetMaster;
}
public void setSetMaster(boolean isSetMaster) {
this.isSetMaster = isSetMaster;
}
@XmlAttribute(name = "setSize")
public int getSetSize() {
return this.setSize;
}
public void setSetSize(final int size) {
this.setSize = size;
}
/**
* Store the latest filedate for a set of movie files. Synchronized so that
* the comparisons don't overlap
*
* @param fileDate
*/
public synchronized void addFileDate(Date fileDate) {
if (this.fileDate == null) {
this.fileDate = fileDate;
} else if (fileDate.after(this.fileDate)) {
this.fileDate = fileDate;
}
}
/**
* Overwrite the file date
*
* @param fileDate
*/
public synchronized void setFileDate(Date fileDate) {
this.fileDate = fileDate;
}
public Date getFileDate() {
return fileDate;
}
public void setFileSize(long fileSize) {
this.fileSize = this.fileSize + fileSize;
}
public long getFileSize() {
return fileSize;
}
public String getFileSizeString() {
return StringTools.formatFileSize(fileSize);
}
public void setAspectRatio(String aspectRatio) {
this.aspect = aspectRatio;
}
public String getAspectRatio() {
return aspect;
}
// ***** All the graphics methods go here *****
// ***** Posters
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getPosterURL() {
return posterURL;
}
/**
* Should be called only from ArtworkScanner. Avoid calling this inside
* MoviePlugin Also called from MovieNFOScanner
*
* @param posterURL
*/
public void setPosterURL(String posterURL) {
if (StringTools.isValidString(posterURL)) {
// If the artwork URL is different, then change it, otheriwse leave alone.
if (!posterURL.equalsIgnoreCase(this.posterURL)) {
setDirty(DirtyFlag.POSTER, Boolean.TRUE);
setDirty(DirtyFlag.INFO);
this.posterURL = posterURL;
}
} else {
this.posterURL = UNKNOWN;
}
}
@XmlElement(name = "posterFile")
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getPosterFilename() {
return posterFilename;
}
public void setPosterFilename(String posterFilename) {
if (StringTools.isValidString(posterFilename)) {
this.posterFilename = posterFilename;
} else {
this.posterFilename = UNKNOWN;
}
}
@XmlElement(name = "detailPosterFile")
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getDetailPosterFilename() {
return detailPosterFilename;
}
public void setDetailPosterFilename(String detailPosterFilename) {
if (StringTools.isValidString(detailPosterFilename)) {
this.detailPosterFilename = detailPosterFilename;
} else {
this.detailPosterFilename = UNKNOWN;
}
}
// ***** Thumbnails
@XmlElement(name = "thumbnail")
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getThumbnailFilename() {
return this.thumbnailFilename;
}
public void setThumbnailFilename(String thumbnailFilename) {
if (StringTools.isValidString(thumbnailFilename)) {
this.thumbnailFilename = thumbnailFilename;
} else {
this.thumbnailFilename = UNKNOWN;
}
}
// ***** Footer
@XmlElement(name = "footer")
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public List getFooterFilename() {
return this.footerFilename;
}
public void setFooterFilename(String footerFilename, Integer inx) {
// Can't change the passed parameter
String ff;
if (StringUtils.isBlank(footerFilename)) {
ff = UNKNOWN;
} else {
ff = FileTools.makeSafeFilename(footerFilename);
}
if (this.footerFilename.size() <= inx) {
while (this.footerFilename.size() < inx) {
this.footerFilename.add(UNKNOWN);
}
this.footerFilename.add(ff);
} else {
this.footerFilename.set(inx, ff);
}
}
// ***** Fanart
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getFanartURL() {
return fanartURL;
}
public void setFanartURL(String fanartURL) {
if (StringTools.isValidString(fanartURL)) {
if (!fanartURL.equalsIgnoreCase(this.fanartURL)) {
setDirty(DirtyFlag.FANART, Boolean.TRUE);
setDirty(DirtyFlag.INFO);
this.fanartURL = fanartURL;
}
} else {
this.fanartURL = UNKNOWN;
}
}
@XmlElement(name = "fanartFile")
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getFanartFilename() {
return fanartFilename;
}
public void setFanartFilename(String fanartFilename) {
if (StringTools.isValidString(fanartFilename)) {
this.fanartFilename = fanartFilename;
} else {
this.fanartFilename = UNKNOWN;
}
}
// ***** Banners
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getBannerURL() {
return bannerURL;
}
public void setBannerURL(String bannerURL) {
if (StringTools.isValidString(bannerURL)) {
if (!bannerURL.equalsIgnoreCase(this.bannerURL)) {
setDirty(DirtyFlag.BANNER, Boolean.TRUE);
setDirty(DirtyFlag.INFO);
this.bannerURL = bannerURL;
}
} else {
this.bannerURL = UNKNOWN;
}
}
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getBannerFilename() {
return bannerFilename;
}
public void setBannerFilename(String bannerFilename) {
if (StringTools.isValidString(bannerFilename)) {
this.bannerFilename = bannerFilename;
} else {
this.bannerFilename = UNKNOWN;
}
}
// ***** ClearLogo
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getClearLogoURL() {
return clearLogoURL;
}
public void setClearLogoURL(String clearLogoURL) {
if (StringTools.isValidString(clearLogoURL)) {
if (!clearLogoURL.equalsIgnoreCase(this.clearLogoURL)) {
setDirty(DirtyFlag.CLEARLOGO, Boolean.TRUE);
setDirty(DirtyFlag.INFO);
this.clearLogoURL = clearLogoURL;
}
} else {
this.clearArtURL = UNKNOWN;
}
}
@XmlElement(name = "clearLogoFile")
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getClearLogoFilename() {
return clearLogoFilename;
}
public void setClearLogoFilename(String clearLogoFilename) {
if (StringTools.isValidString(clearLogoFilename)) {
this.clearLogoFilename = clearLogoFilename;
} else {
this.clearLogoFilename = UNKNOWN;
}
}
// ***** ClearArt
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getClearArtURL() {
return clearArtURL;
}
public void setClearArtURL(String clearArtURL) {
if (StringTools.isValidString(clearArtURL)) {
if (!clearArtURL.equalsIgnoreCase(this.clearArtURL)) {
setDirty(DirtyFlag.CLEARART, Boolean.TRUE);
setDirty(DirtyFlag.INFO);
this.clearArtURL = clearArtURL;
}
} else {
this.clearArtURL = UNKNOWN;
}
}
@XmlElement(name = "clearArtFile")
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getClearArtFilename() {
return clearArtFilename;
}
public void setClearArtFilename(String clearArtFilename) {
if (StringTools.isValidString(clearArtFilename)) {
this.clearArtFilename = clearArtFilename;
} else {
this.clearArtFilename = UNKNOWN;
}
}
// ***** TvThumb
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getTvThumbURL() {
return tvThumbURL;
}
public void setTvThumbURL(String tvThumbURL) {
if (StringTools.isValidString(tvThumbURL)) {
if (!tvThumbURL.equalsIgnoreCase(this.tvThumbURL)) {
setDirty(DirtyFlag.TVTHUMB, Boolean.TRUE);
setDirty(DirtyFlag.INFO);
this.tvThumbURL = tvThumbURL;
}
} else {
this.tvThumbURL = UNKNOWN;
}
}
@XmlElement(name = "tvThumbFile")
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getTvThumbFilename() {
return tvThumbFilename;
}
public void setTvThumbFilename(String tvThumbFilename) {
if (StringTools.isValidString(tvThumbFilename)) {
this.tvThumbFilename = tvThumbFilename;
} else {
this.tvThumbFilename = UNKNOWN;
}
}
// ***** SeasonThumb
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getSeasonThumbURL() {
return seasonThumbURL;
}
public void setSeasonThumbURL(String seasonThumbURL) {
if (StringTools.isValidString(seasonThumbURL)) {
if (!seasonThumbURL.equalsIgnoreCase(this.seasonThumbURL)) {
setDirty(DirtyFlag.SEASONTHUMB, Boolean.TRUE);
setDirty(DirtyFlag.INFO);
this.seasonThumbURL = seasonThumbURL;
}
} else {
this.seasonThumbURL = UNKNOWN;
}
}
@XmlElement(name = "seasonThumbFile")
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getSeasonThumbFilename() {
return seasonThumbFilename;
}
public void setSeasonThumbFilename(String seasonThumbFilename) {
if (StringTools.isValidString(seasonThumbFilename)) {
this.seasonThumbFilename = seasonThumbFilename;
} else {
this.seasonThumbFilename = UNKNOWN;
}
}
// ***** MovieDisc
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getMovieDiscURL() {
return movieDiscURL;
}
public void setMovieDiscURL(String movieDiscURL) {
if (StringTools.isValidString(movieDiscURL)) {
if (!movieDiscURL.equalsIgnoreCase(this.movieDiscURL)) {
setDirty(DirtyFlag.MOVIEDISC, Boolean.TRUE);
setDirty(DirtyFlag.INFO);
this.movieDiscURL = movieDiscURL;
}
} else {
this.movieDiscURL = UNKNOWN;
}
}
@XmlElement(name = "movieDiscFile")
@XmlJavaTypeAdapter(UrlCodecAdapter.class)
public String getMovieDiscFilename() {
return movieDiscFilename;
}
public void setMovieDiscFilename(String movieDiscFilename) {
if (StringTools.isValidString(movieDiscFilename)) {
this.movieDiscFilename = movieDiscFilename;
} else {
this.movieDiscFilename = UNKNOWN;
}
}
// ***** END of graphics *****
public Map getIndexes() {
return indexes;
}
public void addIndex(String key, String index) {
if (key != null && index != null) {
indexes.put(key, index);
}
}
public void setIndexes(Map indexes) {
this.indexes = new HashMap(indexes);
}
@XmlTransient
public boolean isOverrideYear() {
return overrideYear;
}
public void setOverrideYear(boolean overrideYear) {
this.overrideYear = overrideYear;
}
public String getTagline() {
return tagline;
}
public void setTagline(String tagline) {
this.tagline = validateString(tagline, this.tagline);
}
// Read the watched flag
@XmlElement(name = "isWatched")
public boolean isWatched() {
// The watched NFO should override the watched file status
return (watchedFile || watchedNFO);
}
@XmlTransient
public boolean isWatchedNFO() {
return watchedNFO;
}
@XmlTransient
public boolean isWatchedFile() {
return watchedFile;
}
// Set the watched flag for files
public void setWatchedFile(boolean watched) {
this.watchedFile = watched;
}
// Set the watched flag for NFO
public void setWatchedNFO(boolean watched) {
this.watchedNFO = watched;
}
@XmlElement
public String getWatchedDateString() {
long returnDate = getWatchedDate();
if (returnDate == 0) {
return Movie.UNKNOWN;
} else {
return new DateTime(returnDate).toString(StringTools.getDateFormatLongString());
}
}
/**
* Look at the associated movie files and return the latest date a file was
* watched
*
* @return
*/
public long getWatchedDate() {
long returnDate = 0;
for (MovieFile mf : movieFiles) {
if (mf.isWatched() && mf.getWatchedDate() > returnDate) {
returnDate = mf.getWatchedDate();
}
}
return returnDate;
}
/**
* @return the artwork
*/
public Set getArtwork() {
return artwork;
}
/**
* @param artwork the artwork to set
*/
public void setArtwork(Set artwork) {
this.artwork = artwork;
}
public void addArtwork(Artwork artwork) {
//TODO: Check to see if the artwork source/type/url exists and add to it rather than overwrite or append to the list
this.artwork.add(artwork);
}
/**
* Check to see if an artwork already exists.
*
* @param artwork
* @return
*/
@SuppressWarnings("unused")
private Artwork artworkExists(Artwork artwork) {
for (Artwork artworkTest : getArtwork(artwork.getType())) {
if (artworkTest.equals(artwork)) {
return artworkTest;
}
}
return null;
}
public Collection getArtwork(ArtworkType artworkType) {
Collection artworkList = new LinkedHashSet();
for (Artwork tempArtwork : this.artwork) {
if (tempArtwork.getType() == artworkType) {
artworkList.add(tempArtwork);
}
}
return artworkList;
}
public String getShowStatus() {
return showStatus;
}
public void setShowStatus(String showStatus) {
this.showStatus = showStatus;
}
public void setMovieScanner(MovieDatabasePlugin movieScanner) {
if (movieScanner != null) {
this.movieScanner = movieScanner;
}
}
@XmlTransient
public MovieDatabasePlugin getMovieScanner() {
return movieScanner;
}
/**
* Copy the movie
*
* @param aMovie
* @return
*/
public static Movie newInstance(Movie aMovie) {
Movie newMovie = new Movie();
newMovie.baseName = aMovie.baseName;
newMovie.baseFilename = aMovie.baseFilename;
newMovie.title = aMovie.title;
newMovie.titleSort = aMovie.titleSort;
newMovie.originalTitle = aMovie.originalTitle;
newMovie.year = aMovie.year;
newMovie.releaseDate = aMovie.releaseDate;
newMovie.plot = aMovie.plot;
newMovie.outline = aMovie.outline;
newMovie.quote = aMovie.quote;
newMovie.tagline = aMovie.tagline;
newMovie.country = aMovie.country;
newMovie.company = aMovie.company;
newMovie.runtime = aMovie.runtime;
newMovie.language = aMovie.language;
newMovie.videoType = aMovie.videoType;
newMovie.subtitles = aMovie.subtitles;
newMovie.container = aMovie.container;
newMovie.resolution = aMovie.resolution;
newMovie.aspect = aMovie.aspect;
newMovie.videoSource = aMovie.videoSource;
newMovie.videoOutput = aMovie.videoOutput;
newMovie.fps = aMovie.fps;
newMovie.certification = aMovie.certification;
newMovie.showStatus = aMovie.showStatus;
newMovie.scrapeLibrary = aMovie.scrapeLibrary;
newMovie.extra = aMovie.extra;
newMovie.trailerExchange = aMovie.trailerExchange;
newMovie.trailerLastScan = aMovie.trailerLastScan;
newMovie.libraryPath = aMovie.libraryPath;
newMovie.movieType = aMovie.movieType;
newMovie.formatType = aMovie.formatType;
newMovie.overrideTitle = aMovie.overrideTitle;
newMovie.overrideYear = aMovie.overrideYear;
newMovie.top250 = aMovie.top250;
newMovie.libraryDescription = aMovie.libraryDescription;
newMovie.prebuf = aMovie.prebuf;
newMovie.posterURL = aMovie.posterURL;
newMovie.posterFilename = aMovie.posterFilename;
newMovie.detailPosterFilename = aMovie.detailPosterFilename;
newMovie.thumbnailFilename = aMovie.thumbnailFilename;
newMovie.fanartURL = aMovie.fanartURL;
newMovie.fanartFilename = aMovie.fanartFilename;
newMovie.bannerURL = aMovie.bannerURL;
newMovie.bannerFilename = aMovie.bannerFilename;
newMovie.clearArtURL = aMovie.clearArtURL;
newMovie.clearArtFilename = aMovie.clearArtFilename;
newMovie.clearLogoURL = aMovie.clearLogoURL;
newMovie.clearLogoFilename = aMovie.clearLogoFilename;
newMovie.tvThumbURL = aMovie.tvThumbURL;
newMovie.tvThumbFilename = aMovie.tvThumbFilename;
newMovie.seasonThumbURL = aMovie.seasonThumbURL;
newMovie.seasonThumbFilename = aMovie.seasonThumbFilename;
newMovie.movieDiscURL = aMovie.movieDiscURL;
newMovie.movieDiscFilename = aMovie.movieDiscFilename;
newMovie.fileDate = aMovie.fileDate;
newMovie.fileSize = aMovie.fileSize;
newMovie.watchedFile = aMovie.watchedFile;
newMovie.watchedNFO = aMovie.watchedNFO;
newMovie.first = aMovie.first;
newMovie.previous = aMovie.first;
newMovie.next = aMovie.next;
newMovie.last = aMovie.last;
newMovie.file = aMovie.file;
newMovie.containerFile = aMovie.containerFile;
newMovie.isSetMaster = aMovie.isSetMaster;
newMovie.setSize = aMovie.setSize;
newMovie.idMap = new HashMap(aMovie.idMap);
newMovie.ratings = new HashMap(aMovie.ratings);
newMovie.directors = new LinkedHashSet(aMovie.directors);
newMovie.sets = new HashMap(aMovie.sets);
newMovie.genres = new TreeSet(aMovie.genres);
newMovie.cast = new LinkedHashSet(aMovie.cast);
newMovie.writers = new LinkedHashSet(aMovie.writers);
newMovie.awards = new ArrayList(aMovie.awards);
newMovie.people = new ArrayList(aMovie.people);
newMovie.artwork = new LinkedHashSet(aMovie.artwork);
newMovie.indexes = new HashMap(aMovie.indexes);
newMovie.movieFiles = new TreeSet(aMovie.movieFiles);
newMovie.extraFiles = new TreeSet(aMovie.extraFiles);
newMovie.dirtyFlags = EnumSet.copyOf(aMovie.dirtyFlags);
newMovie.codecs = new LinkedHashSet(aMovie.codecs);
newMovie.footerFilename = new ArrayList(aMovie.footerFilename);
return newMovie;
}
public Set getCodecs() {
return codecs;
}
public void setCodecs(Set codecs) {
this.codecs = codecs;
setDirty(DirtyFlag.INFO);
}
/**
* Add a codec to the video file.
*
* @param newCodec
*/
public void addCodec(final Codec newCodec) {
// Check to see if the codec already exists
boolean alreadyExists = Boolean.FALSE;
// Store the codecs to delete in an array to prevent a concurent modification exception
ArrayList codecsToDelete = new ArrayList();
for (Codec existingCodec : codecs) {
if (existingCodec.getCodecType() != newCodec.getCodecType()) {
// Codecs are not the same type.
continue;
}
// Checks to see if the Type, Codec, Language and Channels are the same
if (existingCodec.equals(newCodec)) {
// Check to see if the codec is better than an existing one
if (existingCodec.getCodecSource().isBetter(newCodec.getCodecSource())) {
// Found an existing codec which is better
alreadyExists = Boolean.TRUE;
break;
} else {
// Found an existing codec, but newer is better source
codecsToDelete.add(existingCodec);
}
break;
}
}
// Delete codecs if it is not required
for (Codec codecToDelete : codecsToDelete) {
codecs.remove(codecToDelete);
setDirty(DirtyFlag.INFO);
}
codecsToDelete.clear();
// If the codec does not exist, add it to the list
if (!alreadyExists) {
this.codecs.add(newCodec);
setDirty(DirtyFlag.INFO);
}
}
public static List getSortIgnorePrefixes() {
return SORT_IGNORE_PREFIXES;
}
}