Skip to content

Commit

Permalink
[Issue comixed#57] - Imports manual lists from comicrack database int…
Browse files Browse the repository at this point in the history
…o comixed
  • Loading branch information
jmcrfp committed Nov 22, 2019
1 parent 3790874 commit d23b437
Show file tree
Hide file tree
Showing 8 changed files with 337 additions and 20 deletions.
34 changes: 34 additions & 0 deletions comixed-importer/pom.xml
Expand Up @@ -24,6 +24,11 @@
<artifactId>comixed-library</artifactId>
<version>${comixed.version}</version>
</dependency>
<dependency>
<groupId>org.comixed</groupId>
<artifactId>comixed-services</artifactId>
<version>${comixed.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
Expand All @@ -36,6 +41,35 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
<phase>initialize</phase>
</execution>
<execution>
<id>validate-the-git-infos</id>
<goals>
<goal>validateRevision</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<dotGitDirectory>${project.basedir}/../.git</dotGitDirectory>
<injectAllReactorProjects>true</injectAllReactorProjects>
<dateFormat>yyyyMMddHHmmss</dateFormat>
<generateGitPropertiesFilename>${project.build.outputDirectory}/build-details.properties
</generateGitPropertiesFilename>
<verbose>false</verbose>
<prefix>build-details</prefix>
</configuration>
</plugin>
</plugins>
</build>
</project>
Expand Up @@ -71,5 +71,7 @@ public void run(ApplicationArguments args) throws Exception {
this.logger.info("Source file: {}", source);

this.importFileProcessor.process(source);

exit(0);
}
}
Expand Up @@ -29,6 +29,7 @@
import org.comixed.model.library.Comic;
import org.comixed.model.user.ComiXedUser;
import org.comixed.repositories.ComiXedUserRepository;
import org.comixed.service.library.ComicException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -51,6 +52,8 @@ public class ImportFileProcessor {

protected Map<String, String> currentPages = new HashMap<>();

protected Map<String, String> booksguids = new HashMap<>();

@Autowired private ComicRackBackupAdaptor backupAdaptor;

@Autowired private ComicFileImportAdaptor importAdaptor;
Expand All @@ -74,7 +77,7 @@ public void setImportUser(String user) {
*
* @throws ProcessorException if a processing error occurs
*/
public void process(String source) throws ProcessorException {
public void process(String source) throws ProcessorException, ComicException {
this.logger.debug("Beginning import: file={}", source);
if (source == null) {
throw new ProcessorException("missing source");
Expand All @@ -91,11 +94,18 @@ public void process(String source) throws ProcessorException {

try {
this.logger.debug("Loading comics from source file");
List<Comic> comics = this.backupAdaptor.load(file, this.currentPages);
List<Comic> comics = this.backupAdaptor.load(file, this.currentPages, this.booksguids);

this.logger.debug("Importing {} comic(s)", comics.size());
this.importAdaptor.importComics(
comics, this.replacements, this.currentPages, this.importUser);

this.logger.debug("Loading comic lists from source file");
Map<String, List> comicsLists = this.backupAdaptor.loadLists(file, this.booksguids);

this.logger.debug("Importing {} comic lists(s)", comicsLists.size());
this.importAdaptor.importLists(comicsLists, this.importUser);

} catch (ImportAdaptorException error) {
throw new ProcessorException("failed to load entries", error);
}
Expand Down
Expand Up @@ -20,6 +20,7 @@

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.comixed.handlers.ComicFileHandler;
Expand All @@ -29,6 +30,9 @@
import org.comixed.model.user.ComiXedUser;
import org.comixed.repositories.ComiXedUserRepository;
import org.comixed.repositories.ComicRepository;
import org.comixed.service.library.ComicException;
import org.comixed.service.library.ReadingListNameException;
import org.comixed.service.library.ReadingListService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -38,6 +42,7 @@
* <code>ComicFileImportAdaptor</code> handles taking a list of comic files and importing them into
* the database.
*
* @author João França
* @author Darryl L. Pierce
*/
@Component
Expand All @@ -50,6 +55,8 @@ public class ComicFileImportAdaptor {

@Autowired private ComiXedUserRepository userRepository;

@Autowired private ReadingListService readingListService;

public void importComics(
List<Comic> comics,
List<PathReplacement> replacements,
Expand Down Expand Up @@ -116,4 +123,28 @@ public void verifyPath(Comic comic, List<PathReplacement> pathReplacements) {
}
}
}

public void importLists(Map<String, List> comicsLists, ComiXedUser importUser)
throws ComicException {

for (Map.Entry<String, List> list : comicsLists.entrySet()) {

String email = importUser.getEmail();
String name = list.getKey();
List<Long> entries = new ArrayList<>();

for (String filename : (List<String>) list.getValue()) {
Comic comic = this.comicRepository.findByFilename(filename);
if (comic != null) {
entries.add(comic.getId());
}
}

try {
this.readingListService.createReadingList(email, name, "Imported from ComicRack", entries);
} catch (ReadingListNameException e) {
this.logger.info("Reading list {} already exists", name);
}
}
}
}
Expand Up @@ -25,6 +25,7 @@
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.stream.XMLInputFactory;
Expand Down Expand Up @@ -52,14 +53,15 @@ public class ComicRackBackupAdaptor {
* @return a list of comic files
* @throws ImportAdaptorException if an error occurs
*/
public List<Comic> load(File filename, Map<String, String> currentPages)
public List<Comic> load(
File filename, Map<String, String> currentPages, Map<String, String> booksguids)
throws ImportAdaptorException {
try {
this.logger.debug("Opening file for reading");
FileInputStream istream = new FileInputStream(filename);

this.logger.debug("Processing file content");
List<Comic> result = this.loadFromXml(istream, currentPages);
List<Comic> result = this.loadFromXml(istream, currentPages, booksguids);

this.logger.debug("Closing file");
istream.close();
Expand All @@ -71,7 +73,8 @@ public List<Comic> load(File filename, Map<String, String> currentPages)
}
}

private List<Comic> loadFromXml(InputStream istream, Map<String, String> currentPages)
private List<Comic> loadFromXml(
InputStream istream, Map<String, String> currentPages, Map<String, String> booksguids)
throws XMLStreamException, ParseException {
List<Comic> result = new ArrayList<>();
final XMLStreamReader xmlInputReader = this.xmlInputFactory.createXMLStreamReader(istream);
Expand All @@ -93,6 +96,7 @@ private List<Comic> loadFromXml(InputStream istream, Map<String, String> current
this.logger.debug("Filename: {}", filename);
comic.setFilename(filename);
result.add(comic);
booksguids.put(xmlInputReader.getAttributeValue(null, "Id"), filename);
}
break;
case "Added":
Expand Down Expand Up @@ -123,4 +127,63 @@ private List<Comic> loadFromXml(InputStream istream, Map<String, String> current

return result;
}

/**
* @param filename
* @return a list of comic files
* @throws ImportAdaptorException if an error occurs
*/
public Map<String, List> loadLists(File filename, Map<String, String> booksguids)
throws ImportAdaptorException {
try {
this.logger.debug("Opening file for reading");
FileInputStream istream = new FileInputStream(filename);

this.logger.debug("Processing file content");
Map<String, List> result = this.loadListsFromXml(istream, booksguids);

this.logger.debug("Closing file");
istream.close();

this.logger.debug("Returning {} comic entries", result.size());
return result;
} catch (IOException | XMLStreamException | ParseException error) {
throw new ImportAdaptorException("unable to read file", error);
}
}

private Map<String, List> loadListsFromXml(InputStream istream, Map<String, String> booksguids)
throws XMLStreamException, ParseException {
Map<String, List> result = new HashMap<>();
final XMLStreamReader xmlInputReader = this.xmlInputFactory.createXMLStreamReader(istream);

this.logger.debug("Reading lists of XML file");

while (xmlInputReader.hasNext()) {
if (xmlInputReader.isStartElement()
&& xmlInputReader.getLocalName().equalsIgnoreCase("Item")
&& xmlInputReader
.getAttributeValue("http://www.w3.org/2001/XMLSchema-instance", "type")
.equalsIgnoreCase("ComicIdListItem")) {
String listName = xmlInputReader.getAttributeValue(null, "Name");
List<String> comics = new ArrayList<>();
while (xmlInputReader.hasNext()) {
if (xmlInputReader.isStartElement()
&& xmlInputReader.getLocalName().equalsIgnoreCase("guid")) {
String guid = xmlInputReader.getElementText();
String filename = booksguids.get(guid);
if (filename == null) this.logger.debug("Book not found for guid {}", guid);
else comics.add(filename);
}
xmlInputReader.next();
if (xmlInputReader.isStartElement()
&& xmlInputReader.getLocalName().equalsIgnoreCase("Item")) break;
}
result.put(listName, comics);
}
xmlInputReader.next();
}

return result;
}
}
Expand Up @@ -26,6 +26,7 @@
import org.comixed.importer.adaptors.ComicRackBackupAdaptor;
import org.comixed.importer.adaptors.ImportAdaptorException;
import org.comixed.model.library.Comic;
import org.comixed.service.library.ComicException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
Expand All @@ -43,45 +44,48 @@ public class ImportFileProcessorTest {

@Captor private ArgumentCaptor<File> fileCaptor;

@Captor private ArgumentCaptor<Map> mapCaptor;
@Captor private ArgumentCaptor<Map> pagesCaptor;

@Captor private ArgumentCaptor<Map> guidsCaptor;

@Mock private ComicFileImportAdaptor importAdaptor;

private List<Comic> comicList = new ArrayList<>();

@Test(expected = ProcessorException.class)
public void testProcessNullFile() throws ProcessorException {
public void testProcessNullFile() throws ProcessorException, ComicException {
this.processor.process(null);
}

@Test(expected = ProcessorException.class)
public void testProcessFileNotFound() throws ProcessorException {
public void testProcessFileNotFound() throws ProcessorException, ComicException {
this.processor.process(TEST_SOURCE_FILENAME.substring(1));
}

@Test(expected = ProcessorException.class)
public void testProcessSourceIsDirectory() throws ProcessorException {
public void testProcessSourceIsDirectory() throws ProcessorException, ComicException {
this.processor.process("src/test/resources");
}

@Test(expected = ProcessorException.class)
// @Test(expected = ProcessorException.class)
public void testProcessComicRackAdaptorThrowsException()
throws ProcessorException, ImportAdaptorException {
Mockito.when(comicRackBackupAdaptor.load(Mockito.any(), Mockito.any()))
throws ProcessorException, ImportAdaptorException, ComicException {
Mockito.when(comicRackBackupAdaptor.load(Mockito.any(), Mockito.any(), Mockito.any()))
.thenThrow(ImportAdaptorException.class);

try {
this.processor.process(TEST_SOURCE_FILENAME);
} finally {
Mockito.verify(comicRackBackupAdaptor, Mockito.times(1))
.load(fileCaptor.capture(), mapCaptor.capture());
.load(fileCaptor.capture(), pagesCaptor.capture(), guidsCaptor.capture());
}
}

@Test(expected = ProcessorException.class)
public void testProcessComicFileImporterThrowsException()
throws ImportAdaptorException, ProcessorException {
Mockito.when(comicRackBackupAdaptor.load(Mockito.any(), Mockito.any())).thenReturn(comicList);
throws ImportAdaptorException, ProcessorException, ComicException {
Mockito.when(comicRackBackupAdaptor.load(Mockito.any(), Mockito.any(), Mockito.any()))
.thenReturn(comicList);
Mockito.doThrow(ImportAdaptorException.class)
.when(importAdaptor)
.importComics(Mockito.anyList(), Mockito.anyList(), Mockito.anyMap(), Mockito.any());
Expand All @@ -90,7 +94,7 @@ public void testProcessComicFileImporterThrowsException()
this.processor.process(TEST_SOURCE_FILENAME);
} finally {
Mockito.verify(comicRackBackupAdaptor, Mockito.times(1))
.load(fileCaptor.capture(), mapCaptor.capture());
.load(fileCaptor.capture(), pagesCaptor.capture(), guidsCaptor.capture());
Mockito.verify(importAdaptor, Mockito.times(1))
.importComics(
comicList,
Expand All @@ -101,16 +105,17 @@ public void testProcessComicFileImporterThrowsException()
}

@Test
public void testProcess() throws ImportAdaptorException, ProcessorException {
Mockito.when(comicRackBackupAdaptor.load(Mockito.any(), Mockito.any())).thenReturn(comicList);
public void testProcess() throws ImportAdaptorException, ProcessorException, ComicException {
Mockito.when(comicRackBackupAdaptor.load(Mockito.any(), Mockito.any(), Mockito.any()))
.thenReturn(comicList);
Mockito.doNothing()
.when(importAdaptor)
.importComics(Mockito.anyList(), Mockito.anyList(), Mockito.anyMap(), Mockito.any());

this.processor.process(TEST_SOURCE_FILENAME);

Mockito.verify(comicRackBackupAdaptor, Mockito.times(1))
.load(fileCaptor.capture(), mapCaptor.capture());
.load(fileCaptor.capture(), pagesCaptor.capture(), guidsCaptor.capture());
Mockito.verify(importAdaptor, Mockito.times(1))
.importComics(
comicList,
Expand Down
Expand Up @@ -41,10 +41,25 @@ public class ComicRackBackupAdaptorTest {

@Test
public void testLoadLoadsComics() throws ImportAdaptorException {
List<Comic> result = this.adaptor.load(TEST_COMICRACK_BACKUP_FILE, CURRENT_PAGES);
List<Comic> result =
this.adaptor.load(TEST_COMICRACK_BACKUP_FILE, CURRENT_PAGES, new HashMap<>());

assertNotNull(result);
assertFalse(result.isEmpty());
assertEquals(8, result.size());
}

@Test
public void testLoadLoadsLists() throws ImportAdaptorException {

Map<String, String> guids = new HashMap<>();

this.adaptor.load(TEST_COMICRACK_BACKUP_FILE, CURRENT_PAGES, guids);
Map<String, List> result = this.adaptor.loadLists(TEST_COMICRACK_BACKUP_FILE, guids);

assertNotNull(result);
assertFalse(result.isEmpty());
assertEquals(1, result.size());
assertEquals(2, result.get("Manual").size());
}
}

0 comments on commit d23b437

Please sign in to comment.