package monakhv.samlib.db; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.stmt.PreparedQuery; import com.j256.ormlite.stmt.QueryBuilder; import monakhv.samlib.db.entity.*; import monakhv.samlib.log.Log; import java.sql.SQLException; import java.util.HashMap; import java.util.List; /* * Copyright 2015 Dmitry Monakhov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * * * 2/16/15. */ /** * COL_ID+" integer primary key autoincrement, "+ * COL_BOOK_LINK +" text,"+ * COL_BOOK_AUTHOR +" text,"+ * COL_BOOK_TITLE +" text,"+ * COL_BOOK_FORM +" text,"+ * COL_BOOK_SIZE +" INTEGER,"+ * COL_BOOK_GROUP_ID +" INTEGER,"+ * COL_BOOK_DATE +" timestamp,"+//from the samlib * COL_BOOK_DESCRIPTION +" text,"+ * COL_BOOK_AUTHOR_ID +" INTEGER NOT NULL,"+ * COL_BOOK_MTIME +" timestamp, "+//updated in the db * COL_BOOK_ISNEW +" BOOLEAN DEFAULT '0' NOT NULL"+ */ public class BookController { private static final String DEBUG_TAG = "BookController"; private final Dao<Book, Integer> dao; private final Dao<SelectedBook, Integer> selectedDao; private final GroupBookController grpCtl; BookController(DaoBuilder sql) { dao = sql.getBookDao(); selectedDao = sql.getSelectedBookDao(); grpCtl = new GroupBookController(sql); } void operate(Author author) { HashMap<String, GroupBook> groupBookHashMap = new HashMap<>();//cache for GroupBook lookup for (Book book : author.getBooks()) { //Log.i(DEBUG_TAG, "Book: " + book.getUri() + " - " + book.isIsNew() + " Operation: " + book.getSqlOperation().name()); switch (book.getSqlOperation()) { case DELETE: if (!book.isPreserve()) { delete(book); } break; case UPDATE: book.setAuthor(author); restoreGroup(author, book, groupBookHashMap); update(book); break; case INSERT: book.setAuthor(author); restoreGroup(author, book, groupBookHashMap); insert(book); break; case NONE: break; } } } /** * Restore GroupBook for the Book according to the Author and Group Name * * @param author Author * @param book Book * @param groupBookHashMap Cache to store lookup value */ private void restoreGroup(Author author, Book book, HashMap<String, GroupBook> groupBookHashMap) { String gName = book.getGroupBook().getName(); if (groupBookHashMap.containsKey(gName)) {//Group found into cache book.setGroupBook(groupBookHashMap.get(gName)); } else { GroupBook gb = grpCtl.getByAuthorAndName(author, gName); if (gb != null) { groupBookHashMap.put(gName, gb); book.setGroupBook(gb); } } } /** * Update book into database * * @param book The object to update * @return id */ public int update(Book book) { int res; try { res = dao.update(book); } catch (SQLException e) { Log.e(DEBUG_TAG, "can not update: ", e); return -1; } return res; } /** * Insert new Book object into Database * * @param book object to insert * @return id */ public long insert(Book book) { int res; try { res = dao.create(book); } catch (SQLException e) { Log.e(DEBUG_TAG, "can not insert: ", e); return -1; } return res; } /** * Delete Book object * * @param book objects to delete * @return id */ private int delete(Book book) { int res; try { res = dao.delete(book); } catch (SQLException e) { Log.e(DEBUG_TAG, "can not delete: ", e); return -1; } return res; } public List<Book> getAll() { return null; } /** * Get Books of given author * * @param author the Author * @param order Sort order in row format * @return List of the books */ public synchronized List<Book> getAll(Author author, String order) { List<Book> res; QueryBuilder<Book, Integer> qb = dao.queryBuilder(); if (order != null) { qb.orderByRaw(order); } try { res = dao.query(getPrepared(qb, author)); } catch (SQLException e) { Log.e(DEBUG_TAG, "getAll: Query error: ", e); return null; } return res; } /** * Return list of new book for given author * * @param author Author * @param order sort order * @return List of author */ private List<Book> getAllNew(Author author, String order) { List<Book> res; QueryBuilder<Book, Integer> qb = dao.queryBuilder(); if (order != null) { qb.orderByRaw(order); } try { qb.where() .eq(SQLController.COL_BOOK_AUTHOR_ID, author) .and() .eq(SQLController.COL_BOOK_ISNEW, true); res = dao.query(qb.prepare()); } catch (SQLException e) { Log.e(DEBUG_TAG, "getAllNew: Query error: ", e); return null; } return res; } private PreparedQuery<Book> getPrepared(QueryBuilder<Book, Integer> qb, Author author) throws SQLException { qb.where().eq(SQLController.COL_BOOK_AUTHOR_ID, author); return qb.prepare(); } public GroupBook getSelectedGroup(String order) { GroupBook groupBook = new GroupBook(); groupBook.setId(SamLibConfig.GROUP_ID_SELECTED); List<Book> books = getSelected(order); groupBook.setBooks(books); int newNumber = 0; for (Book book : books) { if (book.isIsNew()) { ++newNumber; } } groupBook.setNewNumber(newNumber); return groupBook; } /** * Get Selected Book * * @param order Sort order if not null * @return List of selected books */ private List<Book> getSelected(String order) { QueryBuilder<Book, Integer> qbBooks = dao.queryBuilder(); QueryBuilder<SelectedBook, Integer> qbSelected = selectedDao.queryBuilder(); try { qbBooks.join(qbSelected); } catch (SQLException e) { Log.e(DEBUG_TAG, "getSelected: join error", e); return null; } if (order != null) { qbBooks.orderByRaw(order); } try { //qbBooks.where().eq(SQLController.COL_BOOK_GROUP_ID, Book.SELECTED_GROUP_ID); return dao.query(qbBooks.prepare()); } catch (SQLException e) { Log.e(DEBUG_TAG, "getSelected: query error", e); return null; } } /** * Find all books for the group and put them into the group object * * @param groupBook Group object to search books for * @param order book sort order */ public void getBookForGroup(GroupBook groupBook, String order) { if (groupBook.getId() == -1) {//All books for the author groupBook.setBooks(getAll(groupBook.getAuthor(), order)); groupBook.setNewNumber(getAllNew(groupBook.getAuthor(), order).size()); return; } final QueryBuilder<Book, Integer> qbBooks = dao.queryBuilder(); if (order != null) { qbBooks.orderByRaw(order); } try { qbBooks.where() .eq(SQLController.COL_BOOK_GROUP_ID, groupBook); groupBook.setBooks(dao.query(qbBooks.prepare())); } catch (SQLException e) { Log.e(DEBUG_TAG, "getBookForGroup: query error", e); } } public Book getById(long id) { Integer dd = (int) id; try { return dao.queryForId(dd); } catch (SQLException e) { return null; } } public List<Book> getBooksByAuthor(Author a) { return getAll(a, null); } /** * Clean unread mark for book * * @param book the book to clean flag */ public void markRead(Book book) { book.setIsNew(false); update(book); updateNewNumber(book); } /** * set Unread mark for book * * @param book the book to set flag */ public void markUnRead(Book book) { book.setIsNew(true); update(book); updateNewNumber(book); } private void updateNewNumber(Book book) { GroupBook groupBook = grpCtl.getByBook(book); if (groupBook != null) { updateGroupNewNumber(groupBook); } } /** * Calculate the num,ber for new books into group * * @param groupBook group to make calculation for */ void updateGroupNewNumber(GroupBook groupBook) { getBookForGroup(groupBook, null); int newNumber = 0; for (Book b : groupBook.getBooks()) { if (b.isIsNew()) { ++newNumber; } } groupBook.setNewNumber(newNumber); grpCtl.update(groupBook); } /** * Set book selected * * @param book the book to make selected */ public void setSelected(Book book) { if (book.isSelected()) { return; } book.setSelected(true); try { selectedDao.create(new SelectedBook(book)); dao.update(book); } catch (SQLException e) { Log.e(DEBUG_TAG, "setSelected: sql error ", e); } } /** * Make book deselected - remove from selection * * @param book Book to deselect */ public void setDeselected(Book book) { if (!book.isSelected()) { return; } book.setSelected(false); update(book); QueryBuilder<SelectedBook, Integer> qb = selectedDao.queryBuilder(); List<SelectedBook> selected; try { selected = selectedDao.query(qb.where().eq(SQLController.COL_BOOK_ID, book).prepare()); } catch (SQLException e) { Log.e(DEBUG_TAG, "setDeselected: sql query error ", e); return; } if (selected.size() != 1) { Log.e(DEBUG_TAG, "setDeselected: result size error " + selected.size()); } try { selectedDao.delete(selected.get(0)); } catch (SQLException e) { Log.e(DEBUG_TAG, "setDeselected: sql delete error ", e); } } }