From c9eac04050b02c1e44eaba7c08671a057dad0610 Mon Sep 17 00:00:00 2001 From: Matthieu Gautier Date: Thu, 30 Aug 2018 10:53:27 +0200 Subject: [PATCH] Make the Library`s book vector private. Move a lot of methods from Manager to Library. Because books is private and thoses methods are better in Library. --- include/library.h | 74 +++++++-- include/manager.h | 62 -------- src/library.cpp | 214 +++++++++++++++++++++++++ src/manager.cpp | 389 ++++------------------------------------------ 4 files changed, 301 insertions(+), 438 deletions(-) diff --git a/include/library.h b/include/library.h index 7b4b847aa..0497e5a5c 100644 --- a/include/library.h +++ b/include/library.h @@ -38,6 +38,7 @@ namespace kiwix { enum supportedIndexType { UNKNOWN, XAPIAN }; +class OPDSDumper; /** * A class to store information about a book (a zim file) @@ -88,6 +89,7 @@ class Book */ class Library { + std::vector books; public: Library(); ~Library(); @@ -105,26 +107,72 @@ class Library */ bool addBook(const Book& book); + Book& getBookById(const std::string& id); + + bool removeBookByIndex(const unsigned int bookIndex); /** * Remove a book from the library. * - * @param bookIndex the index of the book to remove. - * @return True + * @param id the id of the book to remove. + * @return True if the book were in the lirbrary and has been removed. */ - bool removeBookByIndex(const unsigned int bookIndex); - vector books; + bool removeBookById(const std::string& id); - /* - * 'current' is the variable storing the current content/book id - * in the library. This is used to be able to load per default a - * content. As Kiwix may work with many library XML files, you may - * have "current" defined many time with different values. The - * last XML file read has the priority, Although we do not have an - * library object for each file, we want to be able to fallback to - * an 'old' current book if the one which should be load - * failed. That is the reason why we need a stack here + /** + * Write the library to a file. + * + * @param path the path of the file to write to. + * @return True if the library has been correctly save. */ + bool writeToFile(const std::string& path); + + /** + * Get the number of book in the library. + * + * @param localBooks If we must count local books (books with a path). + * @param remoteBooks If we must count remote books (books with an url) + * @return The number of books. + */ + 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 string& search); + + /** + * Get all langagues of the books in the library. + * + * @return A list of languages. + */ + std::vector getBooksLanguages(); + + /** + * Get all book creators of the books in the library. + * + * @return A list of book creators. + */ + std::vector getBooksCreators(); + + /** + * Get all book publishers of the books in the library. + * + * @return A list of book publishers. + */ + std::vector getBooksPublishers(); + + /** + * Get all book ids of the books in the library. + * + * @return A list of book ids. + */ + std::vector getBooksIds(); + stack current; + friend class OPDSDumper; }; } diff --git a/include/manager.h b/include/manager.h index d1154090f..abbbd8e7d 100644 --- a/include/manager.h +++ b/include/manager.h @@ -99,15 +99,6 @@ class Manager */ bool readOpds(const string& content, const std::string& urlHost); - /** - * Write the library to a file. - * - * @param path the path of the file to write. - * @return True. - */ - bool writeFile(const string path); - - /** * Remove a book from the library. * @@ -193,13 +184,6 @@ class Manager const string url = "", const bool checkMetaData = false); - /** - * Clone and return the internal library. - * - * @return A clone of the library. - */ - Library cloneLibrary(); - /** * Get the book corresponding to an id. * @@ -217,15 +201,6 @@ class Manager */ bool getCurrentBook(Book& book); - /** - * Get the number of book in the library. - * - * @param localBooks If we must count local books (books with a path). - * @param remoteBooks If we must count remote books (books with an url) - * @return The number of books. - */ - unsigned int getBookCount(const bool localBooks, const bool remoteBooks); - /** * Update the "last open date" of a book * @@ -266,43 +241,6 @@ class Manager const string publisher, const string search); - /** - * 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 string& search); - - - /** - * Get all langagues of the books in the library. - * - * @return A list of languages. - */ - vector getBooksLanguages(); - - /** - * Get all book creators of the books in the library. - * - * @return A list of book creators. - */ - vector getBooksCreators(); - - /** - * Get all book publishers of the books in the library. - * - * @return A list of book publishers. - */ - vector getBooksPublishers(); - - /** - * Get all book ids of the books in the library. - * - * @return A list of book ids. - */ - vector getBooksIds(); - string writableLibraryPath; vector bookIdList; diff --git a/src/library.cpp b/src/library.cpp index a38106fba..3ac04f3b2 100644 --- a/src/library.cpp +++ b/src/library.cpp @@ -19,6 +19,8 @@ #include "library.h" +#include + namespace kiwix { /* Constructor */ @@ -136,6 +138,8 @@ Library::Library() : version(KIWIX_LIBRARY_VERSION) Library::~Library() { } + + bool Library::addBook(const Book& book) { /* Try to find it */ @@ -152,9 +156,219 @@ bool Library::addBook(const Book& book) return true; } + bool Library::removeBookByIndex(const unsigned int bookIndex) { books.erase(books.begin() + bookIndex); return true; } + +bool Library::removeBookById(const std::string& id) +{ + auto itr = books.begin(); + for(; itr != books.end(); itr ++) { + if (itr->id == id) { + break; + } + } + if (itr != books.end()) { + books.erase(itr); + return true; + } + return false; +} + +Book& Library::getBookById(const std::string& id) +{ + for(auto& book: books) { + if(book.id == id) { + return book; + } + } + throw std::runtime_error(""); +} + +unsigned int Library::getBookCount(const bool localBooks, + const bool remoteBooks) +{ + unsigned int result = 0; + for (auto& book: books) { + if ((!book.path.empty() && localBooks) + || (book.path.empty() && remoteBooks)) { + result++; + } + } + return result; +} + +Library Library::filter(const std::string& search) { + Library library; + + if (search.empty()) { + return library; + } + + for(auto& book:books) { + if (matchRegex(book.title, "\\Q" + search + "\\E") + || matchRegex(book.description, "\\Q" + search + "\\E")) { + library.addBook(book); + } + } + + return library; +} + +bool Library::writeToFile(const std::string& path) { + pugi::xml_document doc; + + /* Add the library node */ + pugi::xml_node libraryNode = doc.append_child("library"); + + if (!version.empty()) + libraryNode.append_attribute("version") = version.c_str(); + + /* Add each book */ + for (auto& book: books) { + if (!book.readOnly) { + pugi::xml_node bookNode = libraryNode.append_child("book"); + bookNode.append_attribute("id") = book.id.c_str(); + + if (!book.path.empty()) { + bookNode.append_attribute("path") = book.path.c_str(); + } + + if (!book.last.empty() && book.last != "undefined") { + bookNode.append_attribute("last") = book.last.c_str(); + } + + if (!book.indexPath.empty()) + bookNode.append_attribute("indexPath") = book.indexPath.c_str(); + + if (!book.indexPath.empty() || !book.indexPathAbsolute.empty()) { + if (book.indexType == XAPIAN) { + bookNode.append_attribute("indexType") = "xapian"; + } + } + + if (book.origId.empty()) { + if (!book.title.empty()) + bookNode.append_attribute("title") = book.title.c_str(); + + if (!book.name.empty()) + bookNode.append_attribute("name") = book.name.c_str(); + + if (!book.tags.empty()) + bookNode.append_attribute("tags") = book.tags.c_str(); + + if (!book.description.empty()) + bookNode.append_attribute("description") = book.description.c_str(); + + if (!book.language.empty()) + bookNode.append_attribute("language") = book.language.c_str(); + + if (!book.creator.empty()) + bookNode.append_attribute("creator") = book.creator.c_str(); + + if (!book.publisher.empty()) + bookNode.append_attribute("publisher") = book.publisher.c_str(); + + if (!book.favicon.empty()) + bookNode.append_attribute("favicon") = book.favicon.c_str(); + + if (!book.faviconMimeType.empty()) + bookNode.append_attribute("faviconMimeType") + = book.faviconMimeType.c_str(); + } + + if (!book.date.empty()) { + bookNode.append_attribute("date") = book.date.c_str(); + } + + if (!book.url.empty()) { + bookNode.append_attribute("url") = book.url.c_str(); + } + + if (!book.origId.empty()) + bookNode.append_attribute("origId") = book.origId.c_str(); + + if (!book.articleCount.empty()) + bookNode.append_attribute("articleCount") = book.articleCount.c_str(); + + if (!book.mediaCount.empty()) + bookNode.append_attribute("mediaCount") = book.mediaCount.c_str(); + + if (!book.size.empty()) { + bookNode.append_attribute("size") = book.size.c_str(); + } + } + } + + /* saving file */ + return doc.save_file(path.c_str()); +} + +std::vector Library::getBooksLanguages() +{ + std::vector booksLanguages; + std::map booksLanguagesMap; + + for (auto& book: books) { + if (booksLanguagesMap.find(book.language) == booksLanguagesMap.end()) { + if (book.origId.empty()) { + booksLanguagesMap[book.language] = true; + booksLanguages.push_back(book.language); + } + } + } + + return booksLanguages; +} + +std::vector Library::getBooksCreators() +{ + std::vector booksCreators; + std::map booksCreatorsMap; + + for (auto& book: books) { + if (booksCreatorsMap.find(book.creator) == booksCreatorsMap.end()) { + if (book.origId.empty()) { + booksCreatorsMap[book.creator] = true; + booksCreators.push_back(book.creator); + } + } + } + + return booksCreators; +} + +std::vector Library::getBooksIds() +{ + std::vector booksIds; + + for (auto& book: books) { + booksIds.push_back(book.id); + } + + return booksIds; +} + +std::vector Library::getBooksPublishers() +{ + std::vector booksPublishers; + std::map booksPublishersMap; + + for (auto& book:books) { + if (booksPublishersMap.find(book.publisher) == booksPublishersMap.end()) { + if (book.origId.empty()) { + booksPublishersMap[book.publisher] = true; + booksPublishers.push_back(book.publisher); + } + } + } + + return booksPublishers; +} + + + } diff --git a/src/manager.cpp b/src/manager.cpp index 313b0fc88..f7a502cc1 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -194,105 +194,6 @@ bool Manager::readFile(const string nativePath, return retVal; } -bool Manager::writeFile(const string path) -{ - pugi::xml_document doc; - - /* Add the library node */ - pugi::xml_node libraryNode = doc.append_child("library"); - - if (!getCurrentBookId().empty()) { - libraryNode.append_attribute("current") = getCurrentBookId().c_str(); - } - - if (!library.version.empty()) - libraryNode.append_attribute("version") = library.version.c_str(); - - /* Add each book */ - std::vector::iterator itr; - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if (!itr->readOnly) { - this->checkAndCleanBookPaths(*itr, path); - - pugi::xml_node bookNode = libraryNode.append_child("book"); - bookNode.append_attribute("id") = itr->id.c_str(); - - if (!itr->path.empty()) { - bookNode.append_attribute("path") = itr->path.c_str(); - } - - if (!itr->last.empty() && itr->last != "undefined") { - bookNode.append_attribute("last") = itr->last.c_str(); - } - - if (!itr->indexPath.empty()) - bookNode.append_attribute("indexPath") = itr->indexPath.c_str(); - - if (!itr->indexPath.empty() || !itr->indexPathAbsolute.empty()) { - if (itr->indexType == XAPIAN) { - bookNode.append_attribute("indexType") = "xapian"; - } - } - - if (itr->origId.empty()) { - if (!itr->title.empty()) - bookNode.append_attribute("title") = itr->title.c_str(); - - if (!itr->name.empty()) - bookNode.append_attribute("name") = itr->name.c_str(); - - if (!itr->tags.empty()) - bookNode.append_attribute("tags") = itr->tags.c_str(); - - if (!itr->description.empty()) - bookNode.append_attribute("description") = itr->description.c_str(); - - if (!itr->language.empty()) - bookNode.append_attribute("language") = itr->language.c_str(); - - if (!itr->creator.empty()) - bookNode.append_attribute("creator") = itr->creator.c_str(); - - if (!itr->publisher.empty()) - bookNode.append_attribute("publisher") = itr->publisher.c_str(); - - if (!itr->favicon.empty()) - bookNode.append_attribute("favicon") = itr->favicon.c_str(); - - if (!itr->faviconMimeType.empty()) - bookNode.append_attribute("faviconMimeType") - = itr->faviconMimeType.c_str(); - } - - if (!itr->date.empty()) { - bookNode.append_attribute("date") = itr->date.c_str(); - } - - if (!itr->url.empty()) { - bookNode.append_attribute("url") = itr->url.c_str(); - } - - if (!itr->origId.empty()) - bookNode.append_attribute("origId") = itr->origId.c_str(); - - if (!itr->articleCount.empty()) - bookNode.append_attribute("articleCount") = itr->articleCount.c_str(); - - if (!itr->mediaCount.empty()) - bookNode.append_attribute("mediaCount") = itr->mediaCount.c_str(); - - if (!itr->size.empty()) { - bookNode.append_attribute("size") = itr->size.c_str(); - } - } - } - - /* saving file */ - doc.save_file(path.c_str()); - - return true; -} - bool Manager::setCurrentBookId(const string id) { @@ -411,300 +312,62 @@ bool Manager::removeBookByIndex(const unsigned int bookIndex) bool Manager::removeBookById(const string id) { - unsigned int bookIndex = 0; - std::vector::iterator itr; - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if (itr->id == id) { - return this->library.removeBookByIndex(bookIndex); - } - bookIndex++; - } - return false; + return library.removeBookById(id); } -vector Manager::getBooksLanguages() -{ - std::vector booksLanguages; - std::vector::iterator itr; - std::map booksLanguagesMap; - - std::sort( - library.books.begin(), library.books.end(), kiwix::Book::sortByLanguage); - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if (booksLanguagesMap.find(itr->language) == booksLanguagesMap.end()) { - if (itr->origId.empty()) { - booksLanguagesMap[itr->language] = true; - booksLanguages.push_back(itr->language); - } - } - } - - return booksLanguages; -} - -vector Manager::getBooksCreators() -{ - std::vector booksCreators; - std::vector::iterator itr; - std::map booksCreatorsMap; - - std::sort( - library.books.begin(), library.books.end(), kiwix::Book::sortByCreator); - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if (booksCreatorsMap.find(itr->creator) == booksCreatorsMap.end()) { - if (itr->origId.empty()) { - booksCreatorsMap[itr->creator] = true; - booksCreators.push_back(itr->creator); - } - } - } - - return booksCreators; -} - -vector Manager::getBooksIds() -{ - std::vector booksIds; - std::vector::iterator itr; - - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - booksIds.push_back(itr->id); - } - - return booksIds; -} - -vector Manager::getBooksPublishers() -{ - std::vector booksPublishers; - std::vector::iterator itr; - std::map booksPublishersMap; - - std::sort( - library.books.begin(), library.books.end(), kiwix::Book::sortByPublisher); - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if (booksPublishersMap.find(itr->publisher) == booksPublishersMap.end()) { - if (itr->origId.empty()) { - booksPublishersMap[itr->publisher] = true; - booksPublishers.push_back(itr->publisher); - } - } - } - - return booksPublishers; -} - -kiwix::Library Manager::cloneLibrary() -{ - return this->library; -} bool Manager::getCurrentBook(Book& book) { string currentBookId = getCurrentBookId(); if (currentBookId.empty()) { return false; } else { - getBookById(currentBookId, book); + book = library.getBookById(currentBookId); return true; } } -bool Manager::getBookById(const string id, Book& book) -{ - std::vector::iterator itr; - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if (itr->id == id) { - book = *itr; - return true; - } - } - return false; -} - bool Manager::updateBookLastOpenDateById(const string id) -{ - std::vector::iterator itr; - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if (itr->id == id) { - char unixdate[12]; - sprintf(unixdate, "%d", (int)time(NULL)); - itr->last = unixdate; - return true; - } - } - +try { + auto book = library.getBookById(id); + char unixdate[12]; + sprintf(unixdate, "%d", (int)time(NULL)); + book.last = unixdate; + return true; +} catch(...) { return false; } bool Manager::setBookIndex(const string id, const string path, const supportedIndexType type) -{ - std::vector::iterator itr; - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if (itr->id == id) { - itr->indexPath = path; - itr->indexPathAbsolute - = isRelativePath(path) +try { + auto book = library.getBookById(id); + book.indexPath = path; + book.indexPathAbsolute = isRelativePath(path) ? computeAbsolutePath( removeLastPathElement(writableLibraryPath, true, false), path) : path; - itr->indexType = type; - return true; - } - } - + book.indexType = type; + return true; +} catch (...) { return false; } bool Manager::setBookPath(const string id, const string path) -{ - std::vector::iterator itr; - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if (itr->id == id) { - itr->path = path; - itr->pathAbsolute - = isRelativePath(path) - ? computeAbsolutePath( - removeLastPathElement(writableLibraryPath, true, false), - path) - : path; - return true; - } - } - +try { + auto book = library.getBookById(id); + book.path = path; + book.pathAbsolute = isRelativePath(path) + ? computeAbsolutePath( + removeLastPathElement(writableLibraryPath, true, false), + path) + : path; + return true; +} catch(...) { return false; } -void Manager::removeBookPaths() -{ - std::vector::iterator itr; - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - itr->path = ""; - itr->pathAbsolute = ""; - } -} - -unsigned int Manager::getBookCount(const bool localBooks, - const bool remoteBooks) -{ - unsigned int result = 0; - std::vector::iterator itr; - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if ((!itr->path.empty() && localBooks) - || (itr->path.empty() && remoteBooks)) { - result++; - } - } - return result; -} - -bool Manager::listBooks(const supportedListMode mode, - const supportedListSortBy sortBy, - const unsigned int maxSize, - const string language, - const string creator, - const string publisher, - const string search) -{ - this->bookIdList.clear(); - std::vector::iterator itr; - - /* Sort */ - if (sortBy == TITLE) { - std::sort( - library.books.begin(), library.books.end(), kiwix::Book::sortByTitle); - } else if (sortBy == SIZE) { - std::sort( - library.books.begin(), library.books.end(), kiwix::Book::sortBySize); - } else if (sortBy == DATE) { - std::sort( - library.books.begin(), library.books.end(), kiwix::Book::sortByDate); - } else if (sortBy == CREATOR) { - std::sort( - library.books.begin(), library.books.end(), kiwix::Book::sortByCreator); - } else if (sortBy == PUBLISHER) { - std::sort(library.books.begin(), - library.books.end(), - kiwix::Book::sortByPublisher); - } - - /* Special sort for LASTOPEN */ - if (mode == LASTOPEN) { - std::sort(library.books.begin(), - library.books.end(), - kiwix::Book::sortByLastOpen); - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - if (!itr->last.empty()) { - this->bookIdList.push_back(itr->id); - } - } - } else { - /* Generate the list of book id */ - for (itr = library.books.begin(); itr != library.books.end(); ++itr) { - bool ok = true; - - if (mode == LOCAL && itr->path.empty()) { - ok = false; - } - - if (ok == true && mode == REMOTE - && (!itr->path.empty() || itr->url.empty())) { - ok = false; - } - - if (ok == true && maxSize != 0 - && (unsigned int)atoi(itr->size.c_str()) > maxSize * 1024 * 1024) { - ok = false; - } - - if (ok == true && !language.empty() - && !matchRegex(itr->language, language)) { - ok = false; - } - - if (ok == true && !creator.empty() && itr->creator != creator) { - ok = false; - } - - if (ok == true && !publisher.empty() && itr->publisher != publisher) { - ok = false; - } - - if ((ok == true && !search.empty()) - && !(matchRegex(itr->title, "\\Q" + search + "\\E") - || matchRegex(itr->description, "\\Q" + search + "\\E") - || matchRegex(itr->language, "\\Q" + search + "\\E"))) { - ok = false; - } - - if (ok == true) { - this->bookIdList.push_back(itr->id); - } - } - } - - return true; -} - - -Library Manager::filter(const std::string& search) { - Library library; - - if (search.empty()) { - return library; - } - - for(auto book:this->library.books) { - if (matchRegex(book.title, "\\Q" + search + "\\E") - || matchRegex(book.description, "\\Q" + search + "\\E")) { - library.addBook(book); - } - } - - return library; -} void Manager::checkAndCleanBookPaths(Book& book, const string& libraryPath) {