From f1078622851c5f749f60ab911547c782004032d5 Mon Sep 17 00:00:00 2001 From: Stuart Boston Date: Wed, 4 Mar 2015 11:11:22 +0000 Subject: [PATCH] Split out compare movies to utility class --- .../com/omertron/themoviedbapi/Compare.java | 141 ++++++++++++++++++ .../omertron/themoviedbapi/CompareTest.java | 130 ++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 src/main/java/com/omertron/themoviedbapi/Compare.java create mode 100644 src/test/java/com/omertron/themoviedbapi/CompareTest.java diff --git a/src/main/java/com/omertron/themoviedbapi/Compare.java b/src/main/java/com/omertron/themoviedbapi/Compare.java new file mode 100644 index 000000000..9116751bc --- /dev/null +++ b/src/main/java/com/omertron/themoviedbapi/Compare.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2004-2015 Stuart Boston + * + * This file is part of TheMovieDB API. + * + * TheMovieDB API 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 + * any later version. + * + * TheMovieDB API 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 TheMovieDB API. If not, see . + * + */ +package com.omertron.themoviedbapi; + +import com.omertron.themoviedbapi.model2.movie.MovieDb; +import org.apache.commons.lang3.StringUtils; + +/** + * Compare various objects to see if the are logically the same. + * + * Allows for some variance of the details + * + * @author Stuart.Boston + */ +public class Compare { + + // Constants + private static final int YEAR_LENGTH = 4; + + private Compare() { + throw new UnsupportedOperationException("Utility class"); + } + + /** + * Compare the MovieDB object with a title & year + * + * @param moviedb The moviedb object to compare too + * @param title The title of the movie to compare + * @param year The year of the movie to compare exact match + * @return True if there is a match, False otherwise. + */ + public static boolean movies(final MovieDb moviedb, final String title, final String year) { + return movies(moviedb, title, year, 0, true); + } + + /** + * Compare the MovieDB object with a title & year + * + * @param moviedb The moviedb object to compare too + * @param title The title of the movie to compare + * @param year The year of the movie to compare + * @param maxDistance The Levenshtein Distance between the two titles. 0 = + * exact match + * @param caseSensitive true if the comparison is to be case sensitive + * @return True if there is a match, False otherwise. + */ + public static boolean movies(final MovieDb moviedb, final String title, final String year, int maxDistance, boolean caseSensitive) { + if ((moviedb == null) || (StringUtils.isBlank(title))) { + return false; + } + + String primaryTitle, firstCompareTitle, secondCompareTitle; + if (caseSensitive) { + primaryTitle = title; + firstCompareTitle = moviedb.getOriginalTitle(); + secondCompareTitle = moviedb.getTitle(); + } else { + primaryTitle = title.toLowerCase(); + firstCompareTitle = moviedb.getTitle().toLowerCase(); + secondCompareTitle = moviedb.getOriginalTitle().toLowerCase(); + } + + if (isValidYear(year) && isValidYear(moviedb.getReleaseDate())) { + // Compare with year + String movieYear = moviedb.getReleaseDate().substring(0, YEAR_LENGTH); + return movieYear.equals(year) && compareTitles(primaryTitle, firstCompareTitle, secondCompareTitle, maxDistance); + } + + // Compare without year + return compareTitles(primaryTitle, firstCompareTitle, secondCompareTitle, maxDistance); + } + + /** + * Compare a title with two other titles. + * + * @param primaryTitle Primary title + * @param firstCompareTitle First title to compare with + * @param secondCompareTitle Second title to compare with + * @param maxDistance Maximum difference between the titles + * @return + */ + private static boolean compareTitles(String primaryTitle, String firstCompareTitle, String secondCompareTitle, int maxDistance) { + // Compare with the first title + if (compareDistance(primaryTitle, firstCompareTitle, maxDistance)) { + return true; + } + + // Compare with the other title + return compareDistance(primaryTitle, secondCompareTitle, maxDistance); + } + + /** + * Compare the MovieDB object with a title & year, case sensitive + * + * @param moviedb + * @param title + * @param year + * @param maxDistance + * @return + */ + public static boolean movies(final MovieDb moviedb, final String title, final String year, int maxDistance) { + return Compare.movies(moviedb, title, year, maxDistance, true); + } + + /** + * Compare the Levenshtein Distance between the two strings + * + * @param title1 + * @param title2 + * @param distance + */ + private static boolean compareDistance(final String title1, final String title2, int distance) { + return StringUtils.getLevenshteinDistance(title1, title2) <= distance; + } + + /** + * Check the year is not blank or UNKNOWN + * + * @param year + */ + private static boolean isValidYear(final String year) { + return StringUtils.isNotBlank(year) && !"UNKNOWN".equals(year); + } +} diff --git a/src/test/java/com/omertron/themoviedbapi/CompareTest.java b/src/test/java/com/omertron/themoviedbapi/CompareTest.java new file mode 100644 index 000000000..48837addf --- /dev/null +++ b/src/test/java/com/omertron/themoviedbapi/CompareTest.java @@ -0,0 +1,130 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.omertron.themoviedbapi; + +import com.omertron.themoviedbapi.model2.movie.MovieDb; +import org.apache.commons.lang3.StringUtils; +import org.junit.After; +import org.junit.AfterClass; +import static org.junit.Assert.assertTrue; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @author Stuart.Boston + */ +public class CompareTest { + + private static final Logger LOG = LoggerFactory.getLogger(CompareTest.class); + + private static MovieDb moviedb; + private static final String TITLE_MAIN = "Blade Runner"; + private static final String TITLE_OTHER = "Blade Runner Directors Cut"; + private static final String YEAR_FULL = "1982-01-01"; + private static final String YEAR_SHORT = "1982"; + + private static final boolean CASE_SENSITIVE = true; + private static final boolean NOT_CASE_SENSITIVE = false; + + public CompareTest() { + } + + @BeforeClass + public static void setUpClass() { + TestLogger.Configure(); + + // Set the default comparison movie + moviedb = new MovieDb(); + moviedb.setTitle(TITLE_MAIN); + moviedb.setOriginalTitle(TITLE_OTHER); + moviedb.setReleaseDate(YEAR_FULL); + } + + @AfterClass + public static void tearDownClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + /** + * Exact match + */ + @Test + public void testExactMatch() { + int maxDistance = 0; + boolean result; + + result = Compare.movies(moviedb, TITLE_MAIN, YEAR_SHORT, maxDistance, CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, TITLE_OTHER, YEAR_SHORT, maxDistance, CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, TITLE_MAIN, YEAR_SHORT, maxDistance, NOT_CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, TITLE_OTHER, YEAR_SHORT, maxDistance, NOT_CASE_SENSITIVE); + assertTrue(result); + + result = Compare.movies(moviedb, TITLE_MAIN, "", maxDistance, CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, TITLE_OTHER, "", maxDistance, CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, TITLE_MAIN, "", maxDistance, NOT_CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, TITLE_OTHER, "", maxDistance, NOT_CASE_SENSITIVE); + assertTrue(result); + } + + /** + * Close match + */ + @Test + public void testCloseMatch() { + int maxDistance = 6; + boolean result; + + String closeMain = "bloderannar"; + String closeOther = "Blade Runner Dir Cut"; + + // Make sure they are close enough + int currentDistance; + + currentDistance = StringUtils.getLevenshteinDistance(TITLE_MAIN, closeMain); + LOG.info("Distance between '{}' and '{}' is {}", TITLE_MAIN, closeMain, currentDistance); + assertTrue(currentDistance <= maxDistance); + + currentDistance = StringUtils.getLevenshteinDistance(TITLE_OTHER, closeOther); + LOG.info("Distance between '{}' and '{}' is {}", TITLE_OTHER, closeOther, currentDistance); + assertTrue(currentDistance <= maxDistance); + + result = Compare.movies(moviedb, closeMain, YEAR_SHORT, maxDistance, CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, closeOther, YEAR_SHORT, maxDistance, CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, closeMain, YEAR_SHORT, maxDistance, NOT_CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, closeOther, YEAR_SHORT, maxDistance, NOT_CASE_SENSITIVE); + assertTrue(result); + + result = Compare.movies(moviedb, closeMain, "", maxDistance, CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, closeOther, "", maxDistance, CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, closeMain, "", maxDistance, NOT_CASE_SENSITIVE); + assertTrue(result); + result = Compare.movies(moviedb, closeOther, "", maxDistance, NOT_CASE_SENSITIVE); + assertTrue(result); + } + +}