package com.gmail.dpierron.calibre.opds;
/**
* Class for implementing the AllBooks sub-catalog
* Inherits from:
* -> BooksSubcatalog - methods for listing contained books.
* -> SubCatalog
*/
import com.gmail.dpierron.calibre.datamodel.Book;
import com.gmail.dpierron.calibre.datamodel.Series;
import com.gmail.dpierron.tools.i18n.Localization;
import com.gmail.dpierron.tools.Helper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class AllBooksSubCatalog extends BooksSubCatalog {
private final static Logger logger = LogManager.getLogger(AllBooksSubCatalog.class);
//------------------ CONSTRUCTORS ------------------------
public AllBooksSubCatalog(List<Book> books) {
super(books);
sortBooks();
setCatalogType(Constants.ALLBOOKS_TYPE);
}
/**
* Version of catalog constructor where we can force sort by Title if wanted
* @param stuffToFilterOut
* @param subbooks
* @param sortByTitle
*/
public AllBooksSubCatalog(List<Object> stuffToFilterOut,
List<Book> subbooks,
boolean sortByTitle) {
super(stuffToFilterOut, subbooks);
if (sortByTitle)
sortBooksByTitle(getBooks());
else
sortBooks();
setCatalogType(Constants.ALLBOOKS_TYPE);
}
/**
* Version of catalog constructor when we may want items filetered out
* @param stuffToFilterOut
* @param books
*/
public AllBooksSubCatalog(List<Object> stuffToFilterOut, List<Book> books) {
super(stuffToFilterOut, books);
sortBooks();
setCatalogType(Constants.ALLBOOKS_TYPE);
}
//------------------ METHODS ------------------------
public boolean isBookTheStepUnit() {
return true;
}
/**
* Sort books according to the profile settings
*/
private void sortBooks() {
if (currentProfile.getOrderAllBooksBySeries()) {
// sort the books by series
sortBooksBySeries(getBooks());
} else {
// sort the books by title
sortBooksByTitle(getBooks());
}
}
/**
* Sort the list of books sorted with the following key sequence:
* - Series (alphabetically)
* - Series-Index (numerically ascending)
* - Book Title (Alphabetically for case where series-Index is the same)
*
* NOTE: This could be in the more generic BooksSubCatalog class, but since
* it is only ever used from this class it has been place here.
*
* TODO: Bug c2o131 - We seem to occasionally get an exception thrown inside the Java libraries
* Not sure at the moment why this should be the case as nothing obvious shows up
* It looks as it only occurs when series information is set and the series indexes are
* the same for the book objects that are being compared but this needs confirming and
* in fact may be due to some other currently unknown factor.
* THINK THIS MAY NOW BE FIXED - NEED FURTHER CHECKING TO ENSURE THIS IS THE CASE
*
* @param books
*/
void sortBooksBySeries(List<Book> books) {
// logger.trace("sortBooksBySeries: enter");
try {
Collections.sort(books, new Comparator<Book>() {
public int compare(Book o1, Book o2) {
// logger.trace("o1=" + o1 + ", o2=" + o2);
assert (o1 != null) && (o2 != null);
// logger.trace("comparing books " + o1.getTitle() + "(" + o1.getId() + ") " + o2.getTitle() + "(" + o2.getId() + ")");
Series series1 = o1.getSeries();
Series series2 = o2.getSeries();
// logger.trace("series1=" + series1 + ", series2=" + series2);
if ((series1 == null) && (series2 == null)) {
// both series are null, we need to compare the book titles (as always...)
String title1;
String title2;
if (currentProfile.getSortUsingTitle()) {
title1 = o1.getTitle();
title2 = o2.getTitle();
} else {
title1 = o1.getTitle_Sort();
title2 = o2.getTitle_Sort();
}
// logger.trace("comparing title '" + title1.toString() + "' to '" + title2.toString() + "'");
try {
int result = Helper.checkedCollatorCompareIgnoreCase(title1, title2, collator);
// logger.trace("return=" + result);
return result;
} catch (Exception e) {
logger.error("Error sorting between titles '" + title1.toString() + "' and '" + title2.toString() + "'");
return 0;
}
}
if (series1 == null) {
// only series2 set so assume series2 sorts greater than series1
// logger.trace("return 1");
return 1;
}
if (series2 == null) {
// only series1 set so assume series2 sorts less than series2
// logger.trace("return -1");
return -1;
}
// Both series set if we get to here
assert (series1 != null) && (series2 != null);
if (!series1.getId().equals(series2.getId())) {
// different series, we need to compare the series title
try {
// logger.trace("comparing series " + series1.getName() + "(" + series1.getId() + ") to " + series2.getName() + "(" + series2.getId() + ")");
int result = Helper.checkedCollatorCompareIgnoreCase(series1.getName(), series2.getName(), collator);
// logger.trace("return=" + result);
return result;
} catch (Exception e) {
logger.error("Error sorting between series '" + series1.getName().toString() + "' and '" + series2.getName().toString() + "'");
return 0;
}
}
// same series, we need to compare the index
// logger.trace("o1.index=" + o1.getSerieIndex() + ", o2.index=" + o2.getSerieIndex());
if (o1.getSerieIndex() == o2.getSerieIndex()) {
// series index the same, so we need to sort on the book title
// both series are null, we need to compare the book titles (as always...)
// logger.trace("Same series and series index");
String title1;
String title2;
if (currentProfile.getSortUsingTitle()) {
title1 = o1.getTitle();
title2 = o2.getTitle();
} else {
title1 = o1.getTitle_Sort();
title2 = o2.getTitle_Sort();
}
// logger.trace("comparing title '" + title1.toString() + "' to '" + title2.toString() + "'");
try {
int result = Helper.checkedCollatorCompareIgnoreCase(title1, title2, collator);
// logger.trace("return=" + result);
return result;
} catch (Exception e) {
logger.error("Error sorting between titles '" + title1.toString() + "' and '" + title2.toString() + "'");
// logger.trace("return 0");
return 0;
}
}
if (o1.getSerieIndex() > o2.getSerieIndex()) {
// logger.trace("return 1");
return 1;
} else {
// logger.trace("return -1");
return -1;
}
} // end of compare()
} // End of Comparator()
); // End of Collections.sort() statement
} catch (Exception e) {
logger.error("Unexpected exception reached trying to sort books by series: " + e);
}
// logger.trace("sortBooksBySeries: exit");
return;
}
public String getSummary() {
if (getBooks().size() > 1)
return Localization.Main.getText("allbooks.alphabetical", getBooks().size());
else if (getBooks().size() == 1)
return Localization.Main.getText("allbooks.alphabetical.single");
else return "";
}
/**
*
* @return
*/
public String getUrn() {
return Constants.INITIAL_URN_PREFIX + getCatalogType();
}
}