diff --git a/comixed-library/src/main/java/org/comixed/model/tasks/TaskType.java b/comixed-library/src/main/java/org/comixed/model/tasks/TaskType.java index 44517e378..e2cf5705d 100644 --- a/comixed-library/src/main/java/org/comixed/model/tasks/TaskType.java +++ b/comixed-library/src/main/java/org/comixed/model/tasks/TaskType.java @@ -29,5 +29,6 @@ public enum TaskType { RESCAN_COMIC, DELETE_COMIC, DELETE_COMICS, - CONVERT_COMIC; + CONVERT_COMIC, + MOVE_COMIC; } diff --git a/comixed-library/src/main/java/org/comixed/repositories/comic/ComicRepository.java b/comixed-library/src/main/java/org/comixed/repositories/comic/ComicRepository.java index 66ee87ec5..a47ef67af 100644 --- a/comixed-library/src/main/java/org/comixed/repositories/comic/ComicRepository.java +++ b/comixed-library/src/main/java/org/comixed/repositories/comic/ComicRepository.java @@ -21,6 +21,7 @@ import java.util.Date; import java.util.List; import org.comixed.model.comic.Comic; +import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -103,4 +104,7 @@ List findIssuesAfterComic( @Query("SELECT c FROM Comic c WHERE c.dateDeleted IS NOT NULL") List findAllMarkedForDeletion(); + + @Query("SELECT c FROM Comic c") + List findComicsToMove(PageRequest page); } diff --git a/comixed-rest-api/src/main/java/org/comixed/controller/library/LibraryController.java b/comixed-rest-api/src/main/java/org/comixed/controller/library/LibraryController.java index 08cb1baf5..6883310a0 100644 --- a/comixed-rest-api/src/main/java/org/comixed/controller/library/LibraryController.java +++ b/comixed-rest-api/src/main/java/org/comixed/controller/library/LibraryController.java @@ -166,4 +166,20 @@ public ClearImageCacheResponse clearImageCache() { return new ClearImageCacheResponse(true); } + + @PostMapping( + value = "/library/move", + produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) + public MoveComicsResponse moveComics(@RequestBody() MoveComicsRequest request) { + String targetDirectory = request.getTargetDirectory(); + String renamingRule = request.getRenamingRule(); + Boolean deletePhysicalFiles = request.getDeletePhysicalFiles(); + + log.info("Moving comics: targetDirectory={}", targetDirectory); + log.info(" : renamingRule={}", renamingRule); + this.libraryService.moveComics(deletePhysicalFiles, targetDirectory, renamingRule); + + return new MoveComicsResponse(true); + } } diff --git a/comixed-rest-api/src/main/java/org/comixed/net/MoveComicsRequest.java b/comixed-rest-api/src/main/java/org/comixed/net/MoveComicsRequest.java new file mode 100644 index 000000000..4b310899e --- /dev/null +++ b/comixed-rest-api/src/main/java/org/comixed/net/MoveComicsRequest.java @@ -0,0 +1,51 @@ +/* + * ComiXed - A digital comic book library management application. + * Copyright (C) 2020, The ComiXed Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package org.comixed.net; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class MoveComicsRequest { + @JsonProperty("deletePhysicalFiles") + private Boolean deletePhysicalFiles; + + @JsonProperty("targetDirectory") + private String targetDirectory; + + @JsonProperty("renamingRule") + private String renamingRule; + + public MoveComicsRequest( + Boolean deletePhysicalFiles, String targetDirectory, String renamingRule) { + this.deletePhysicalFiles = deletePhysicalFiles; + this.targetDirectory = targetDirectory; + this.renamingRule = renamingRule; + } + + public Boolean getDeletePhysicalFiles() { + return deletePhysicalFiles; + } + + public String getTargetDirectory() { + return targetDirectory; + } + + public String getRenamingRule() { + return renamingRule; + } +} diff --git a/comixed-rest-api/src/main/java/org/comixed/net/MoveComicsResponse.java b/comixed-rest-api/src/main/java/org/comixed/net/MoveComicsResponse.java new file mode 100644 index 000000000..d3029242c --- /dev/null +++ b/comixed-rest-api/src/main/java/org/comixed/net/MoveComicsResponse.java @@ -0,0 +1,34 @@ +/* + * ComiXed - A digital comic book library management application. + * Copyright (C) 2020, The ComiXed Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package org.comixed.net; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class MoveComicsResponse { + @JsonProperty("success") + private boolean success; + + public MoveComicsResponse(boolean success) { + this.success = success; + } + + public boolean isSuccess() { + return this.success; + } +} diff --git a/comixed-rest-api/src/test/java/org/comixed/controller/library/LibraryControllerTest.java b/comixed-rest-api/src/test/java/org/comixed/controller/library/LibraryControllerTest.java index 703f1693a..5d6718554 100644 --- a/comixed-rest-api/src/test/java/org/comixed/controller/library/LibraryControllerTest.java +++ b/comixed-rest-api/src/test/java/org/comixed/controller/library/LibraryControllerTest.java @@ -57,6 +57,8 @@ public class LibraryControllerTest { private static final boolean TEST_RENAME_PAGES = RANDOM.nextBoolean(); private static final Boolean TEST_DELETE_PHYSICAL_FILES = RANDOM.nextBoolean(); private static final int TEST_CACHE_ENTRIES_CLEARED = RANDOM.nextInt(); + private static final String TEST_RENAMING_RULE = "PUBLISHER/SERIES/VOLUME/SERIES vVOLUME #ISSUE"; + private static final String TEST_DESTINATION_DIRECTORY = "/home/comixedreader/Documents/comics"; @InjectMocks private LibraryController libraryController; @Mock private LibraryService libraryService; @@ -255,4 +257,22 @@ public void testClearImageCacheWithError() throws LibraryException { Mockito.verify(libraryService, Mockito.times(1)).clearImageCache(); } + + @Test + public void testMoveLibrary() { + Mockito.doNothing() + .when(libraryService) + .moveComics(Mockito.anyBoolean(), Mockito.anyString(), Mockito.anyString()); + + MoveComicsResponse result = + libraryController.moveComics( + new MoveComicsRequest( + TEST_DELETE_PHYSICAL_FILES, TEST_DESTINATION_DIRECTORY, TEST_RENAMING_RULE)); + + assertNotNull(result); + assertTrue(result.isSuccess()); + + Mockito.verify(libraryService, Mockito.times(1)) + .moveComics(TEST_DELETE_PHYSICAL_FILES, TEST_DESTINATION_DIRECTORY, TEST_RENAMING_RULE); + } } diff --git a/comixed-services/src/main/java/org/comixed/service/library/LibraryService.java b/comixed-services/src/main/java/org/comixed/service/library/LibraryService.java index a72de3104..2223c578e 100644 --- a/comixed-services/src/main/java/org/comixed/service/library/LibraryService.java +++ b/comixed-services/src/main/java/org/comixed/service/library/LibraryService.java @@ -36,6 +36,7 @@ import org.comixed.service.user.ComiXedUserException; import org.comixed.service.user.UserService; import org.comixed.task.model.ConvertComicsWorkerTask; +import org.comixed.task.model.MoveComicsWorkerTask; import org.comixed.task.runner.Worker; import org.comixed.utils.Utils; import org.springframework.beans.factory.ObjectFactory; @@ -56,6 +57,7 @@ public class LibraryService { @Autowired private Worker worker; @Autowired private Utils utils; @Autowired private PageCacheService pageCacheService; + @Autowired private ObjectFactory moveComicsTaskObjectFactory; public List getComicsUpdatedSince( String email, Date latestUpdatedDate, int maximumComics, long lastComicId) { @@ -164,4 +166,22 @@ public void clearImageCache() throws LibraryException { throw new LibraryException("failed to clean image cache directory", error); } } + + /** + * Moves all comics in the library, renaming them using the specified naming rule. + * + * @param deletePhysicalFiles + * @param directory the root directory + * @param renamingRule the name rule + */ + public void moveComics(Boolean deletePhysicalFiles, String directory, String renamingRule) { + log.debug("Creating move comics task"); + MoveComicsWorkerTask task = this.moveComicsTaskObjectFactory.getObject(); + log.debug("Setting directory: {}", directory); + task.setDirectory(directory); + log.debug("Setting renaming rule: {}", renamingRule); + task.setRenamingRule(renamingRule); + log.debug("Enqueuing task"); + this.worker.addTasksToQueue(task); + } } diff --git a/comixed-services/src/test/java/org/comixed/service/library/LibraryServiceTest.java b/comixed-services/src/test/java/org/comixed/service/library/LibraryServiceTest.java index 6a706d90e..7fba67e0b 100644 --- a/comixed-services/src/test/java/org/comixed/service/library/LibraryServiceTest.java +++ b/comixed-services/src/test/java/org/comixed/service/library/LibraryServiceTest.java @@ -21,6 +21,8 @@ import org.comixed.service.user.ComiXedUserException; import org.comixed.service.user.UserService; import org.comixed.task.model.ConvertComicsWorkerTask; +import org.comixed.task.model.MoveComicsWorkerTask; +import org.comixed.task.model.WorkerTask; import org.comixed.task.runner.Worker; import org.comixed.utils.Utils; import org.junit.Before; @@ -46,6 +48,9 @@ public class LibraryServiceTest { private static final Long TEST_USER_ID = 723L; private static final String TEST_IMAGE_CACHE_DIRECTORY = "/home/ComiXedReader/.comixed/image-cache"; + private static final String TEST_DIRECTORY = "/home/comixedreader/Documents/comics"; + private static final String TEST_RENAMING_RULES = + "$PUBLISHER/$SERIES/$VOLUME/$SERIES [v$VOLUME] #$ISSUE $COVERDATE"; @InjectMocks private LibraryService libraryService; @Mock private ComicRepository comicRepository; @@ -64,6 +69,8 @@ public class LibraryServiceTest { @Mock private ComiXedUser user; @Mock private LastReadDatesRepository lastReadDatesRepository; @Mock private PageCacheService pageCacheService; + @Mock private ObjectFactory moveComicsTaskObjectFactory; + @Mock private MoveComicsWorkerTask moveComicsWorkerTask; private List comicList = new ArrayList<>(); private Comic comic1 = new Comic(); @@ -233,4 +240,16 @@ public void testClearImageCacheError() throws LibraryException, IOException { Mockito.verify(pageCacheService, Mockito.times(1)).getRootDirectory(); Mockito.verify(utils, Mockito.times(1)).deleteDirectoryContents(TEST_IMAGE_CACHE_DIRECTORY); } + + @Test + public void testMoveComics() { + Mockito.when(moveComicsTaskObjectFactory.getObject()).thenReturn(moveComicsWorkerTask); + Mockito.doNothing().when(worker).addTasksToQueue(Mockito.any(WorkerTask.class)); + + libraryService.moveComics(TEST_DELETE_PHYSICAL_FILES, TEST_DIRECTORY, TEST_RENAMING_RULES); + + Mockito.verify(moveComicsWorkerTask, Mockito.times(1)).setDirectory(TEST_DIRECTORY); + Mockito.verify(moveComicsWorkerTask, Mockito.times(1)).setRenamingRule(TEST_RENAMING_RULES); + Mockito.verify(worker, Mockito.times(1)).addTasksToQueue(moveComicsWorkerTask); + } } diff --git a/comixed-tasks/src/main/java/org/comixed/task/encoders/MoveComicTaskEncoder.java b/comixed-tasks/src/main/java/org/comixed/task/encoders/MoveComicTaskEncoder.java new file mode 100644 index 000000000..ab329a1e5 --- /dev/null +++ b/comixed-tasks/src/main/java/org/comixed/task/encoders/MoveComicTaskEncoder.java @@ -0,0 +1,109 @@ +/* + * ComiXed - A digital comic book library management application. + * Copyright (C) 2020, The ComiXed Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package org.comixed.task.encoders; + +import lombok.extern.log4j.Log4j2; +import org.comixed.model.comic.Comic; +import org.comixed.model.tasks.Task; +import org.comixed.model.tasks.TaskType; +import org.comixed.repositories.tasks.TaskRepository; +import org.comixed.task.model.MoveComicWorkerTask; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +/** + * MoveComicTaskEncoder encodes instances of {@link MoveComicWorkerTask}. + * + * @author Darryl L. Pierce + */ +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +@Log4j2 +public class MoveComicTaskEncoder extends AbstractTaskEncoder { + public static final String DIRECTORY = "destination-directory"; + public static final String RENAMING_RULE = "renaming-rule"; + + @Autowired private ObjectFactory moveComicWorkerTaskObjectFactory; + @Autowired private TaskRepository taskRepository; + + private Comic comic; + private String directory; + private String renamingRule; + + @Override + public Task encode() { + log.debug( + "encoding move comic task: id={} directory={} rename rule={}", + this.comic.getId(), + this.directory, + this.renamingRule); + + Task result = new Task(); + result.setTaskType(TaskType.MOVE_COMIC); + result.setComic(this.comic); + result.setProperty(DIRECTORY, this.directory); + result.setProperty(RENAMING_RULE, this.renamingRule); + + return result; + } + + @Override + public MoveComicWorkerTask decode(Task task) { + this.taskRepository.delete(task); + + log.debug("Decoding move comic task: id={}", task.getId()); + + MoveComicWorkerTask result = this.moveComicWorkerTaskObjectFactory.getObject(); + result.setComic(task.getComic()); + result.setDirectory(task.getProperty(DIRECTORY)); + result.setRenamingRule(task.getProperty(RENAMING_RULE)); + + return result; + } + + /** + * Sets the comic to be moved. + * + * @param comic the comic + */ + public void setComic(Comic comic) { + this.comic = comic; + } + + /** + * Sets the root directory into which the comic is to be moved. + * + * @param directory the directory + */ + public void setDirectory(String directory) { + this.directory = directory; + } + + /** + * Sets the renaming rule to be applied. + * + * @param renamingRule the renaming rule + */ + public void setRenamingRule(String renamingRule) { + this.renamingRule = renamingRule; + } +} diff --git a/comixed-tasks/src/main/java/org/comixed/task/model/MoveComicWorkerTask.java b/comixed-tasks/src/main/java/org/comixed/task/model/MoveComicWorkerTask.java index 583f71812..249e826ea 100644 --- a/comixed-tasks/src/main/java/org/comixed/task/model/MoveComicWorkerTask.java +++ b/comixed-tasks/src/main/java/org/comixed/task/model/MoveComicWorkerTask.java @@ -45,18 +45,24 @@ public class MoveComicWorkerTask extends AbstractWorkerTask { private Comic comic; private String destination; + private String renamingRule; public void setComic(Comic comic) { this.comic = comic; } - public void setDestination(String destination) { + public void setDirectory(String destination) { this.destination = destination; } @Override public void startTask() throws WorkerTaskException { - File sourceFile = new File(this.comic.getFilename()); + File sourceFile = null; + try { + sourceFile = this.renameOriginalFile(); + } catch (IOException error) { + throw new WorkerTaskException("Could not rename original comic file", error); + } File destFile = new File(this.getRelativeDestination(), getRelativeComicFilename()); String defaultExtension = FilenameUtils.getExtension(comic.getFilename()); destFile = @@ -87,6 +93,16 @@ public void startTask() throws WorkerTaskException { } } + private File renameOriginalFile() throws IOException { + String originalFilename = this.comic.getFilename(); + String newFilename = originalFilename + "-old"; + File result = new File(newFilename); + + log.debug("Renaming comic file: {} => {}", originalFilename, newFilename); + FileUtils.moveFile(new File(originalFilename), result); + return result; + } + private String getRelativeDestination() { StringBuffer result = new StringBuffer(this.destination); @@ -132,4 +148,13 @@ protected String createDescription() { return result.toString(); } + + /** + * Sets the renaming rule to use. + * + * @param renamingRule the renaming rule + */ + public void setRenamingRule(String renamingRule) { + this.renamingRule = renamingRule; + } } diff --git a/comixed-tasks/src/main/java/org/comixed/task/model/MoveComicsWorkerTask.java b/comixed-tasks/src/main/java/org/comixed/task/model/MoveComicsWorkerTask.java new file mode 100644 index 000000000..e3624141a --- /dev/null +++ b/comixed-tasks/src/main/java/org/comixed/task/model/MoveComicsWorkerTask.java @@ -0,0 +1,98 @@ +/* + * ComiXed - A digital comic book library management application. + * Copyright (C) 2020, The ComiXed Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package org.comixed.task.model; + +import java.util.List; +import lombok.extern.log4j.Log4j2; +import org.comixed.model.comic.Comic; +import org.comixed.repositories.comic.ComicRepository; +import org.comixed.repositories.tasks.TaskRepository; +import org.comixed.task.encoders.MoveComicTaskEncoder; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Component; + +/** + * MoveComicsWorkerTask handles encoding instances of {@link MoveComicTask} to move + * individual comics. + * + * @author Darryl L. Pierce + */ +@Component +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +@Log4j2 +public class MoveComicsWorkerTask extends AbstractWorkerTask { + private static final int MAX_COMIC_PAGE = 50; + + @Autowired private ObjectFactory moveComicWorkerTaskEncoderObjectFactory; + + @Autowired private TaskRepository taskRepository; + @Autowired private ComicRepository comicRepository; + + private String directory; + private String renamingRule; + + @Override + protected String createDescription() { + return "Moving comics"; + } + + @Override + public void startTask() throws WorkerTaskException { + boolean done = false; + int page = 0; + while (!done) { + log.debug("Preparing to page {} of {} comics", page, MAX_COMIC_PAGE); + List comics = + this.comicRepository.findComicsToMove(PageRequest.of(page, MAX_COMIC_PAGE + 1)); + for (int index = 0; index < comics.size(); index++) { + MoveComicTaskEncoder encoder = this.moveComicWorkerTaskEncoderObjectFactory.getObject(); + + encoder.setComic(comics.get(index)); + encoder.setDirectory(this.directory); + encoder.setRenamingRule(this.renamingRule); + log.debug("Saving move comic task"); + this.taskRepository.save(encoder.encode()); + } + // we're done when we've processed fewer comics than the page size + done = comics.size() < (MAX_COMIC_PAGE + 1); + } + } + + /** + * Sets the directory into which the comics will be moved. + * + * @param directory the directory + */ + public void setDirectory(String directory) { + this.directory = directory; + } + + /** + * Sets the renaming rule to be used. + * + * @param renamingRule the renaming rule + */ + public void setRenamingRule(String renamingRule) { + this.renamingRule = renamingRule; + } +} diff --git a/comixed-tasks/src/main/resources/task-adaptors.properties b/comixed-tasks/src/main/resources/task-adaptors.properties index d50f93206..f98aae48a 100644 --- a/comixed-tasks/src/main/resources/task-adaptors.properties +++ b/comixed-tasks/src/main/resources/task-adaptors.properties @@ -8,3 +8,5 @@ task.adaptors[3].type=DeleteComic task.adaptors[3].name=deleteComicTaskEncoder task.adaptors[4].type=ConvertComic task.adaptors[4].name=convertComicTaskEncoder +task.adaptors[5].type=MoveComic +task.adaptors[5].name=moveComicTaskEncoder diff --git a/comixed-tasks/src/test/java/org/comixed/task/encoders/MoveComicTaskEncoderTest.java b/comixed-tasks/src/test/java/org/comixed/task/encoders/MoveComicTaskEncoderTest.java new file mode 100644 index 000000000..3e9bf34ec --- /dev/null +++ b/comixed-tasks/src/test/java/org/comixed/task/encoders/MoveComicTaskEncoderTest.java @@ -0,0 +1,80 @@ +/* + * ComiXed - A digital comic book library management application. + * Copyright (C) 2020, The ComiXed Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package org.comixed.task.encoders; + +import static junit.framework.TestCase.*; + +import org.comixed.model.comic.Comic; +import org.comixed.model.tasks.Task; +import org.comixed.repositories.tasks.TaskRepository; +import org.comixed.task.model.MoveComicWorkerTask; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.beans.factory.ObjectFactory; + +@RunWith(MockitoJUnitRunner.class) +public class MoveComicTaskEncoderTest { + private static final String TEST_DIRECTORY = "/Users/comixedreader/Documents/comics"; + private static final String TEST_RENAMING_RULE = + "$PUBLISHER/$SERIES/$VOLUME/$SERIES v$VOLUME #$ISSUE ($COVERDATE)"; + + @InjectMocks private MoveComicTaskEncoder moveComicTaskEncoder; + @Mock private TaskRepository taskRepository; + @Mock private ObjectFactory moveComicWorkerTaskObjectFactory; + @Mock private MoveComicWorkerTask moveComicWorkerTask; + @Mock Comic comic; + + @Test + public void testEncode() { + moveComicTaskEncoder.setComic(comic); + moveComicTaskEncoder.setDirectory(TEST_DIRECTORY); + moveComicTaskEncoder.setRenamingRule(TEST_RENAMING_RULE); + + Task result = moveComicTaskEncoder.encode(); + + assertNotNull(result); + assertSame(comic, result.getComic()); + assertEquals(TEST_DIRECTORY, result.getProperty(MoveComicTaskEncoder.DIRECTORY)); + assertEquals(TEST_RENAMING_RULE, result.getProperty(MoveComicTaskEncoder.RENAMING_RULE)); + } + + @Test + public void testDecode() { + Mockito.when(moveComicWorkerTaskObjectFactory.getObject()).thenReturn(moveComicWorkerTask); + + Task task = new Task(); + task.setComic(comic); + task.setProperty(MoveComicTaskEncoder.DIRECTORY, TEST_DIRECTORY); + task.setProperty(MoveComicTaskEncoder.RENAMING_RULE, TEST_RENAMING_RULE); + + MoveComicWorkerTask result = moveComicTaskEncoder.decode(task); + + assertNotNull(result); + assertSame(moveComicWorkerTask, result); + + Mockito.verify(taskRepository, Mockito.times(1)).delete(task); + Mockito.verify(moveComicWorkerTask, Mockito.times(1)).setComic(comic); + Mockito.verify(moveComicWorkerTask, Mockito.times(1)).setDirectory(TEST_DIRECTORY); + Mockito.verify(moveComicWorkerTask, Mockito.times(1)).setRenamingRule(TEST_RENAMING_RULE); + } +} diff --git a/comixed-tasks/src/test/java/org/comixed/task/model/MoveComicsWorkerTaskTest.java b/comixed-tasks/src/test/java/org/comixed/task/model/MoveComicsWorkerTaskTest.java new file mode 100644 index 000000000..ac3083efb --- /dev/null +++ b/comixed-tasks/src/test/java/org/comixed/task/model/MoveComicsWorkerTaskTest.java @@ -0,0 +1,78 @@ +/* + * ComiXed - A digital comic book library management application. + * Copyright (C) 2020, The ComiXed Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package org.comixed.task.model; + +import java.util.ArrayList; +import java.util.List; +import org.comixed.model.comic.Comic; +import org.comixed.model.tasks.Task; +import org.comixed.repositories.comic.ComicRepository; +import org.comixed.repositories.tasks.TaskRepository; +import org.comixed.task.encoders.MoveComicTaskEncoder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.data.domain.PageRequest; + +@RunWith(MockitoJUnitRunner.class) +public class MoveComicsWorkerTaskTest { + private static final String TEST_DIRECTORY = "/users/comixedreader/Documents/comics"; + private static final String TEST_RENAMING_RULE = + "$PUBLISHER/$SERIES/$VOLUME/$SERIES v$VOLUME #$ISSUE ($COVERDATE)"; + + @InjectMocks private MoveComicsWorkerTask moveComicsWorkerTask; + @Mock private ComicRepository comicRepository; + @Mock private ObjectFactory moveComicWorkerTaskEncoderObjectFactory; + @Mock private MoveComicTaskEncoder moveComicTaskEncoder; + @Mock private MoveComicWorkerTask moveComicWorkerTask; + @Mock private Task task; + @Mock private TaskRepository taskRepository; + @Mock private Comic comic; + + private List comicList = new ArrayList<>(); + + @Test + public void testStartTask() throws WorkerTaskException { + Mockito.when(moveComicWorkerTaskEncoderObjectFactory.getObject()) + .thenReturn(moveComicTaskEncoder); + Mockito.when(comicRepository.findComicsToMove(Mockito.any(PageRequest.class))) + .thenReturn(comicList); + Mockito.when(moveComicTaskEncoder.encode()).thenReturn(task); + Mockito.when(taskRepository.save(Mockito.any(Task.class))).thenReturn(task); + + for (int index = 0; index < 25; index++) comicList.add(comic); + moveComicsWorkerTask.setDirectory(TEST_DIRECTORY); + moveComicsWorkerTask.setRenamingRule(TEST_RENAMING_RULE); + + moveComicsWorkerTask.startTask(); + + Mockito.verify(moveComicWorkerTaskEncoderObjectFactory, Mockito.times(comicList.size())) + .getObject(); + Mockito.verify(moveComicTaskEncoder, Mockito.times(comicList.size())).setComic(comic); + Mockito.verify(moveComicTaskEncoder, Mockito.times(comicList.size())) + .setDirectory(TEST_DIRECTORY); + Mockito.verify(moveComicTaskEncoder, Mockito.times(comicList.size())) + .setRenamingRule(TEST_RENAMING_RULE); + Mockito.verify(taskRepository, Mockito.times(comicList.size())).save(task); + } +} diff --git a/comixed-tasks/src/test/resources/application.properties b/comixed-tasks/src/test/resources/application.properties index 8841ad56d..bb3af1164 100644 --- a/comixed-tasks/src/test/resources/application.properties +++ b/comixed-tasks/src/test/resources/application.properties @@ -20,7 +20,7 @@ spring.jackson.deserialization.fail-on-unknown-properties=false # Logging logging.level.root=OFF -logging.level.org.comixed=INFO +logging.level.org.comixed=DEBUG # Comic entry loaders comic.entry.loaders[0].type=jpeg