Skip to content

Commit

Permalink
[Issue #260] Updated REST APIs to return reading lists updated since …
Browse files Browse the repository at this point in the history
…last updated date.
  • Loading branch information
mcpierce committed Jun 21, 2020
1 parent df4ab7d commit cb7a1ab
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 28 deletions.
Expand Up @@ -18,6 +18,7 @@

package org.comixed.repositories.library;

import java.util.Date;
import java.util.List;
import org.comixed.model.comic.Comic;
import org.comixed.model.library.ReadingList;
Expand All @@ -29,8 +30,9 @@

@Repository
public interface ReadingListRepository extends CrudRepository<ReadingList, Long> {
@Query("SELECT list FROM ReadingList list WHERE list.owner = :owner")
List<ReadingList> findAllReadingListsForUser(ComiXedUser owner);
@Query("SELECT l FROM ReadingList l WHERE l.owner = :owner AND l.lastUpdated > :lastUpdated")
List<ReadingList> getAllReadingListsForOwnerUpdatedAfter(
@Param("owner") ComiXedUser owner, @Param("lastUpdated") Date lastUpdated);

@Query("SELECT list FROM ReadingList list WHERE list.owner = :owner AND list.name = :listName")
ReadingList findReadingListForUser(ComiXedUser owner, String listName);
Expand Down
Expand Up @@ -22,6 +22,7 @@

import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.comixed.model.comic.Comic;
Expand Down Expand Up @@ -74,7 +75,8 @@ public void setUp() {

@Test
public void testFindAllReadingListsForUser() {
List<ReadingList> result = repository.findAllReadingListsForUser(reader);
List<ReadingList> result =
repository.getAllReadingListsForOwnerUpdatedAfter(reader, new Date(0L));

assertNotNull(result);
assertEquals(2, result.size());
Expand All @@ -91,6 +93,15 @@ public void testFindAllReadingListsForUser() {
}
}

@Test
public void testFindAllReadingListsForUserNoneUpdated() {
List<ReadingList> result =
repository.getAllReadingListsForOwnerUpdatedAfter(reader, new Date());

assertNotNull(result);
assertTrue(result.isEmpty());
}

@Test
public void testFindReadingListForUser() {
ReadingList result = repository.findReadingListForUser(reader, TEST_EXISTING_LIST_NAME);
Expand Down
Expand Up @@ -25,13 +25,15 @@
import lombok.extern.log4j.Log4j2;
import org.comixed.adaptors.ArchiveType;
import org.comixed.model.comic.Comic;
import org.comixed.model.library.ReadingList;
import org.comixed.model.user.LastReadDate;
import org.comixed.net.ConsolidateLibraryRequest;
import org.comixed.net.ConvertComicsRequest;
import org.comixed.net.GetUpdatedComicsRequest;
import org.comixed.net.GetUpdatedComicsResponse;
import org.comixed.service.comic.ComicService;
import org.comixed.service.library.LibraryService;
import org.comixed.service.library.ReadingListService;
import org.comixed.service.user.UserService;
import org.comixed.views.View;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -48,6 +50,7 @@ public class LibraryController {
@Autowired private LibraryService libraryService;
@Autowired private ComicService comicService;
@Autowired private UserService userService;
@Autowired private ReadingListService readingListService;

@PostMapping(
value = "/library/updates",
Expand All @@ -57,10 +60,11 @@ public class LibraryController {
public GetUpdatedComicsResponse getUpdatedComics(
Principal principal, @RequestBody() GetUpdatedComicsRequest request) {
Date latestUpdateDate = new Date(request.getLastUpdatedDate());
String email = principal.getName();
this.log.info(
"Getting comics updated since {} for {} (max: {}, last id: {}, timeout: {}s)",
latestUpdateDate,
principal.getName(),
email,
request.getMaximumComics(),
request.getLastComicId(),
request.getTimeout());
Expand All @@ -76,10 +80,7 @@ public GetUpdatedComicsResponse getUpdatedComics(
while (!done) {
comics =
this.libraryService.getComicsUpdatedSince(
principal.getName(),
latestUpdateDate,
request.getMaximumComics() + 1,
request.getLastComicId());
email, latestUpdateDate, request.getMaximumComics() + 1, request.getLastComicId());

if (comics.size() > request.getMaximumComics()) {
this.log.debug("More updates are waiting");
Expand Down Expand Up @@ -112,11 +113,21 @@ public GetUpdatedComicsResponse getUpdatedComics(

this.log.debug("Loading updated last read dates");
List<LastReadDate> lastReadDates =
this.libraryService.getLastReadDatesSince(principal.getName(), latestUpdateDate);
this.libraryService.getLastReadDatesSince(email, latestUpdateDate);

this.log.debug("Getting updated reading lists");
List<ReadingList> readingLists =
this.readingListService.getReadingListsForUser(email, latestUpdateDate);

this.log.debug("Returning result");
return new GetUpdatedComicsResponse(
comics, lastComicId, mostRecentUpdate, lastReadDates, moreUpdates, processingCount);
comics,
lastComicId,
mostRecentUpdate,
lastReadDates,
readingLists,
moreUpdates,
processingCount);
}

@PostMapping(value = "/library/convert", consumes = MediaType.APPLICATION_JSON_VALUE)
Expand Down
Expand Up @@ -20,6 +20,7 @@

import com.fasterxml.jackson.annotation.JsonView;
import java.security.Principal;
import java.util.Date;
import java.util.List;
import lombok.extern.log4j.Log4j2;
import org.comixed.model.library.ReadingList;
Expand Down Expand Up @@ -83,15 +84,16 @@ public ReadingList updateReadingList(

@RequestMapping(value = "/lists", method = RequestMethod.GET)
@JsonView(View.ReadingList.class)
public List<ReadingList> getReadingListsForUser(Principal principal) {
public List<ReadingList> getReadingListsForUser(Principal principal, final Date lastUpdated) {
if (principal == null) {
return null;
}
final String email = principal.getName();

this.log.info("Getting reading lists: user={}", email);

final List<ReadingList> result = this.readingListService.getReadingListsForUser(email);
final List<ReadingList> result =
this.readingListService.getReadingListsForUser(email, lastUpdated);

this.log.debug("Returning {} lists{}", result.size(), result.size() == 1 ? "" : "s");
return result;
Expand Down
Expand Up @@ -22,6 +22,7 @@
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.ParseException;
import java.util.Date;
import java.util.Optional;
import javax.imageio.ImageIO;
import javax.swing.*;
Expand Down Expand Up @@ -80,7 +81,7 @@ public OPDSFeed getAllLists() throws ParseException {
return new OPDSNavigationFeed(
"/opds/all?groupByFolder=true",
"Comics - ",
this.readingListService.getReadingListsForUser(authentication.getName()));
this.readingListService.getReadingListsForUser(authentication.getName(), new Date(0L)));
}

@ResponseBody
Expand Down
Expand Up @@ -21,13 +21,16 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonView;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.comixed.model.comic.Comic;
import org.comixed.model.library.ReadingList;
import org.comixed.model.user.LastReadDate;
import org.comixed.views.View;

public class GetUpdatedComicsResponse {

@JsonProperty("comics")
@JsonView(View.ComicList.class)
private List<Comic> comics;
Expand All @@ -45,6 +48,10 @@ public class GetUpdatedComicsResponse {
@JsonView(View.ComicList.class)
private List<LastReadDate> lastReadDates;

@JsonProperty("readingLists")
@JsonView(View.ComicList.class)
private List<ReadingList> readingLists = new ArrayList<>();

@JsonProperty("moreUpdates")
@JsonView(View.ComicList.class)
private boolean moreUpdates;
Expand All @@ -60,12 +67,14 @@ public GetUpdatedComicsResponse(
Long lastComicId,
Date mostRecentUpdate,
List<LastReadDate> lastReadDates,
List<ReadingList> readingLists,
boolean moreUpdates,
long processingCount) {
this.comics = comics;
this.lastComicId = lastComicId;
this.mostRecentUpdate = mostRecentUpdate;
this.lastReadDates = lastReadDates;
this.readingLists = readingLists;
this.moreUpdates = moreUpdates;
this.processingCount = processingCount;
}
Expand Down Expand Up @@ -93,4 +102,8 @@ public boolean hasMoreUpdates() {
public long getProcessingCount() {
return processingCount;
}

public List<ReadingList> getReadingLists() {
return this.readingLists;
}
}
Expand Up @@ -26,6 +26,7 @@
import java.util.Random;
import org.comixed.adaptors.ArchiveType;
import org.comixed.model.comic.Comic;
import org.comixed.model.library.ReadingList;
import org.comixed.model.user.ComiXedUser;
import org.comixed.model.user.LastReadDate;
import org.comixed.net.ConsolidateLibraryRequest;
Expand All @@ -34,6 +35,7 @@
import org.comixed.net.GetUpdatedComicsResponse;
import org.comixed.service.comic.ComicService;
import org.comixed.service.library.LibraryService;
import org.comixed.service.library.ReadingListService;
import org.comixed.service.user.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -66,6 +68,8 @@ public class LibraryControllerTest {
@Mock private Principal principal;
@Mock private ComiXedUser user;
@Mock private List<Long> comicIdList;
@Mock private ReadingListService readingListService;
@Mock private List<ReadingList> readingLists;

@Test
public void testGetUpdatedComics() {
Expand All @@ -82,6 +86,9 @@ public void testGetUpdatedComics() {
Mockito.when(libraryService.getLastReadDatesSince(Mockito.anyString(), Mockito.any(Date.class)))
.thenReturn(lastReadList);
Mockito.when(libraryService.getProcessingCount()).thenReturn(TEST_PROCESSING_COUNT);
Mockito.when(
readingListService.getReadingListsForUser(Mockito.anyString(), Mockito.any(Date.class)))
.thenReturn(readingLists);

GetUpdatedComicsResponse result =
libraryController.getUpdatedComics(
Expand All @@ -100,6 +107,7 @@ public void testGetUpdatedComics() {
assertSame(lastReadList, result.getLastReadDates());
assertFalse(result.hasMoreUpdates());
assertEquals(TEST_PROCESSING_COUNT, result.getProcessingCount());
assertEquals(readingLists, result.getReadingLists());

Mockito.verify(libraryService, Mockito.times(1))
.getComicsUpdatedSince(
Expand All @@ -109,6 +117,8 @@ public void testGetUpdatedComics() {
TEST_MOST_RECENT_COMIC_ID);
Mockito.verify(libraryService, Mockito.times(1))
.getLastReadDatesSince(TEST_USER_EMAIL, TEST_LATEST_UPDATED_DATE);
Mockito.verify(readingListService, Mockito.times(1))
.getReadingListsForUser(TEST_USER_EMAIL, TEST_LAST_UPDATED_DATE);
}

@Test
Expand Down Expand Up @@ -214,7 +224,7 @@ public void testConsolidate() {
List<Comic> response =
libraryController.consolidateLibrary(
new ConsolidateLibraryRequest(TEST_DELETE_PHYSICAL_FILES));
k

assertNotNull(response);
assertSame(comicList, response);

Expand Down
Expand Up @@ -22,10 +22,7 @@
import static org.junit.Assert.assertSame;

import java.security.Principal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import org.comixed.model.comic.Comic;
import org.comixed.model.library.ReadingList;
import org.comixed.model.library.ReadingListEntry;
Expand Down Expand Up @@ -55,6 +52,7 @@ public class ReadingListControllerTest {
private static final Long TEST_COMIC_ID_3 = 1002L;
private static final Long TEST_COMIC_ID_4 = 1003L;
private static final Long TEST_COMIC_ID_5 = 1004L;
private static final Date TEST_LAST_UPDATED_DATE = new Date();

static {
TEST_READING_LIST_ENTRIES.add(TEST_COMIC_ID_1);
Expand Down Expand Up @@ -105,15 +103,17 @@ public void testCreateReadingList()
@Test
public void testGetReadingListsForUser() {
Mockito.when(principal.getName()).thenReturn(TEST_USER_EMAIL);
Mockito.when(readingListService.getReadingListsForUser(Mockito.anyString()))
Mockito.when(
readingListService.getReadingListsForUser(Mockito.anyString(), Mockito.any(Date.class)))
.thenReturn(readingLists);

List<ReadingList> result = controller.getReadingListsForUser(principal);
List<ReadingList> result = controller.getReadingListsForUser(principal, TEST_LAST_UPDATED_DATE);

assertNotNull(result);
assertSame(readingLists, result);

Mockito.verify(readingListService, Mockito.times(1)).getReadingListsForUser(TEST_USER_EMAIL);
Mockito.verify(readingListService, Mockito.times(1))
.getReadingListsForUser(TEST_USER_EMAIL, TEST_LAST_UPDATED_DATE);
Mockito.verify(principal, Mockito.atLeast(1)).getName();
}

Expand Down
Expand Up @@ -24,6 +24,7 @@
import java.security.Principal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.comixed.model.comic.Comic;
import org.comixed.model.library.ReadingList;
Expand Down Expand Up @@ -97,7 +98,8 @@ public void testGetAllLists() throws ParseException {
Mockito.when(autentication.getName()).thenReturn(TEST_USER_EMAIL);
Mockito.when(securityContext.getAuthentication()).thenReturn(autentication);
BDDMockito.given(SecurityContextHolder.getContext()).willReturn(securityContext);
Mockito.when(readingListService.getReadingListsForUser(TEST_USER_EMAIL))
Mockito.when(
readingListService.getReadingListsForUser(Mockito.anyString(), Mockito.any(Date.class)))
.thenReturn(readingLists);

OPDSFeed result = controller.getAllLists();
Expand Down
Expand Up @@ -83,13 +83,13 @@ private void loadComics(final List<Long> entries, final ReadingList readingList)
}
}

public List<ReadingList> getReadingListsForUser(final String email) {
this.log.debug("Getting reading lists for user: email={}", email);
public List<ReadingList> getReadingListsForUser(final String email, final Date lastUpdated) {
this.log.debug("Getting reading lists for user: email={} updated after={}", email, lastUpdated);

this.log.debug("Getting owner");
final ComiXedUser owner = this.userRepository.findByEmail(email);

return this.readingListRepository.findAllReadingListsForUser(owner);
return this.readingListRepository.getAllReadingListsForOwnerUpdatedAfter(owner, lastUpdated);
}

@Transactional
Expand Down
Expand Up @@ -51,6 +51,7 @@ public class ReadingListServiceTest {
private static final Long TEST_COMIC_ID_5 = 1004L;
private static final Long TEST_USER_ID = 17L;
private static final Long TEST_OTHER_USER_ID = 29L;
private static final Date TEST_LAST_UPDATED_DATE = new Date();

static {
TEST_READING_LIST_ENTRIES.add(TEST_COMIC_ID_1);
Expand Down Expand Up @@ -135,16 +136,20 @@ public void testCreateReadingListName()
@Test
public void testGetReadingListsForUser() {
Mockito.when(userRepository.findByEmail(Mockito.anyString())).thenReturn(user);
Mockito.when(readingListRepository.findAllReadingListsForUser(Mockito.any(ComiXedUser.class)))
Mockito.when(
readingListRepository.getAllReadingListsForOwnerUpdatedAfter(
Mockito.any(ComiXedUser.class), Mockito.any(Date.class)))
.thenReturn(readingLists);

List<ReadingList> result = readingListService.getReadingListsForUser(TEST_USER_EMAIL);
List<ReadingList> result =
readingListService.getReadingListsForUser(TEST_USER_EMAIL, TEST_LAST_UPDATED_DATE);

assertNotNull(result);
assertSame(readingLists, result);

Mockito.verify(userRepository, Mockito.times(1)).findByEmail(TEST_USER_EMAIL);
Mockito.verify(readingListRepository, Mockito.times(1)).findAllReadingListsForUser(user);
Mockito.verify(readingListRepository, Mockito.times(1))
.getAllReadingListsForOwnerUpdatedAfter(user, TEST_LAST_UPDATED_DATE);
}

@Test(expected = NoSuchReadingListException.class)
Expand Down

0 comments on commit cb7a1ab

Please sign in to comment.