diff --git a/include/book.h b/include/book.h index 92fd7afb9..ffc9a408b 100644 --- a/include/book.h +++ b/include/book.h @@ -46,12 +46,6 @@ class Book void update(const Reader& reader); void updateFromXml(const pugi::xml_node& node, const std::string& baseDir); void updateFromOpds(const pugi::xml_node& node); - static bool sortByTitle(const Book& a, const Book& b); - static bool sortBySize(const Book& a, const Book& b); - static bool sortByDate(const Book& a, const Book& b); - static bool sortByCreator(const Book& a, const Book& b); - static bool sortByPublisher(const Book& a, const Book& b); - static bool sortByLanguage(const Book& a, const Book& b); std::string getHumanReadableIdFromPath(); bool readOnly() const { return m_readOnly; } diff --git a/include/library.h b/include/library.h index 66dc64230..bf919ccc0 100644 --- a/include/library.h +++ b/include/library.h @@ -32,6 +32,8 @@ namespace kiwix class Book; class OPDSDumper; +enum supportedListSortBy { UNSORTED, TITLE, SIZE, DATE, CREATOR, PUBLISHER }; +enum supportedListMode { ALL, REMOTE, LOCAL }; /** * A Library store several books. */ @@ -82,14 +84,6 @@ class Library */ unsigned int getBookCount(const bool localBooks, const bool remoteBooks); - /** - * Filter the library and generate a new one with the keep elements. - * - * @param search List only books with search in the title or description. - * @return A `Library`. - */ - Library filter(const std::string& search); - /** * Get all langagues of the books in the library. * @@ -118,6 +112,43 @@ class Library */ std::vector getBooksIds(); + /** + * Filter the library and generate a new one with the keep elements. + * + * This is equivalent to `listBookIds(ALL, UNSORTED, search)`. + * + * @param search List only books with search in the title or description. + * @return The list of bookIds corresponding to the query. + */ + std::vector filter(const std::string& search); + + + /** + * List books in the library. + * + * @param mode The mode of listing : + * - ALL list all books. + * (LOCAL and REMOTE. Other filters are applied). + * - LOCAL list only local books. + * - REMOTE list only remote books. + * @param sortBy Attribute to sort by the book list. + * @param search List only books with search in the title, description. + * @param language List only books in this language. + * @param creator List only books of this creator. + * @param publisher List only books of this publisher. + * @param maxSize Do not list book bigger than maxSize. + * Set to 0 to cancel this filter. + * @return The list of bookIds corresponding to the query. + */ + std::vector listBooksIds( + supportedListMode = ALL, + supportedListSortBy sortBy = UNSORTED, + const std::string& search = "", + const std::string& language = "", + const std::string& creator = "", + const std::string& publisher = "", + size_t maxSize = 0); + friend class OPDSDumper; }; } diff --git a/include/manager.h b/include/manager.h index d0e46fc56..08e8cbcb1 100644 --- a/include/manager.h +++ b/include/manager.h @@ -33,8 +33,6 @@ class xml_document; namespace kiwix { -enum supportedListMode { LASTOPEN, REMOTE, LOCAL }; -enum supportedListSortBy { TITLE, SIZE, DATE, CREATOR, PUBLISHER }; /** * A tool to manage a `Library`. diff --git a/src/book.cpp b/src/book.cpp index 6d06f62bc..eb0798b81 100644 --- a/src/book.cpp +++ b/src/book.cpp @@ -35,36 +35,6 @@ Book::Book() : m_readOnly(false) Book::~Book() { } -/* Sort functions */ -bool Book::sortByTitle(const kiwix::Book& a, const kiwix::Book& b) -{ - return a.m_title < b.m_title; -} - -bool Book::sortByDate(const kiwix::Book& a, const kiwix::Book& b) -{ - return a.m_date < b.m_date; -} - -bool Book::sortBySize(const kiwix::Book& a, const kiwix::Book& b) -{ - return a.m_size < b.m_size; -} - -bool Book::sortByPublisher(const kiwix::Book& a, const kiwix::Book& b) -{ - return a.m_publisher < b.m_publisher; -} - -bool Book::sortByCreator(const kiwix::Book& a, const kiwix::Book& b) -{ - return a.m_creator < b.m_creator; -} - -bool Book::sortByLanguage(const kiwix::Book& a, const kiwix::Book& b) -{ - return a.m_language < b.m_language; -} bool Book::update(const kiwix::Book& other) { diff --git a/src/library.cpp b/src/library.cpp index c9611ab08..fea5d83b2 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -25,6 +25,7 @@ #include "common/pathTools.h" #include +#include namespace kiwix { @@ -77,24 +78,6 @@ unsigned int Library::getBookCount(const bool localBooks, return result; } -Library Library::filter(const std::string& search) { - Library library; - - if (search.empty()) { - return library; - } - - for(auto& pair:books) { - auto& book = pair.second; - if (matchRegex(book.getTitle(), "\\Q" + search + "\\E") - || matchRegex(book.getDescription(), "\\Q" + search + "\\E")) { - library.addBook(book); - } - } - - return library; -} - bool Library::writeToFile(const std::string& path) { pugi::xml_document doc; auto baseDir = removeLastPathElement(path, true, false); @@ -217,17 +200,6 @@ std::vector Library::getBooksCreators() return booksCreators; } -std::vector Library::getBooksIds() -{ - std::vector booksIds; - - for (auto& pair: books) { - booksIds.push_back(pair.first); - } - - return booksIds; -} - std::vector Library::getBooksPublishers() { std::vector booksPublishers; @@ -247,6 +219,134 @@ std::vector Library::getBooksPublishers() return booksPublishers; } +std::vector Library::getBooksIds() +{ + std::vector bookIds; + for (auto& pair: books) { + bookIds.push_back(pair.first); + } + return bookIds; +} + +std::vector Library::filter(const std::string& search) +{ + if (search.empty()) { + return getBooksIds(); + } + + std::vector bookIds; + for(auto& pair:books) { + auto& book = pair.second; + if (matchRegex(book.getTitle(), "\\Q" + search + "\\E") + || matchRegex(book.getDescription(), "\\Q" + search + "\\E")) { + bookIds.push_back(pair.first); + } + } + + return bookIds; +} + +template +struct Comparator { + Library* lib; + Comparator(Library* lib) : lib(lib) {} + + bool operator() (const std::string& id1, const std::string& id2) { + return get_keys(id1) < get_keys(id2); + } + + std::string get_keys(const std::string& id); + unsigned int get_keyi(const std::string& id); +}; + +template<> +std::string Comparator::get_keys(const std::string& id) +{ + return lib->getBookById(id).getTitle(); +} + +template<> +unsigned int Comparator<SIZE>::get_keyi(const std::string& id) +{ + return lib->getBookById(id).getSize(); +} + +template<> +bool Comparator<SIZE>::operator() (const std::string& id1, const std::string& id2) +{ + return get_keyi(id1) < get_keyi(id2); +} + +template<> +std::string Comparator<DATE>::get_keys(const std::string& id) +{ + return lib->getBookById(id).getDate(); +} + +template<> +std::string Comparator<CREATOR>::get_keys(const std::string& id) +{ + return lib->getBookById(id).getCreator(); +} + +template<> +std::string Comparator<PUBLISHER>::get_keys(const std::string& id) +{ + return lib->getBookById(id).getPublisher(); +} + + +std::vector<std::string> Library::listBooksIds( + supportedListMode mode, + supportedListSortBy sortBy, + const std::string& search, + const std::string& language, + const std::string& creator, + const std::string& publisher, + size_t maxSize) { + + std::vector<std::string> bookIds; + for(auto& pair:books) { + auto& book = pair.second; + if (mode == LOCAL && book.getPath().empty()) + continue; + if (mode == REMOTE && (!book.getPath().empty() || book.getUrl().empty())) + continue; + if (maxSize != 0 && book.getSize() > maxSize) + continue; + if (!language.empty() && book.getLanguage() != language) + continue; + if (!publisher.empty() && book.getPublisher() != publisher) + continue; + if (!creator.empty() && book.getCreator() != creator) + continue; + if (!search.empty() && !(matchRegex(book.getTitle(), "\\Q" + search + "\\E") + || matchRegex(book.getDescription(), "\\Q" + search + "\\E"))) + continue; + bookIds.push_back(pair.first); + } + + switch(sortBy) { + case TITLE: + std::sort(bookIds.begin(), bookIds.end(), Comparator<TITLE>(this)); + break; + case SIZE: + std::sort(bookIds.begin(), bookIds.end(), Comparator<SIZE>(this)); + break; + case DATE: + std::sort(bookIds.begin(), bookIds.end(), Comparator<DATE>(this)); + break; + case CREATOR: + std::sort(bookIds.begin(), bookIds.end(), Comparator<CREATOR>(this)); + break; + case PUBLISHER: + std::sort(bookIds.begin(), bookIds.end(), Comparator<PUBLISHER>(this)); + break; + default: + break; + } + return bookIds; +} }