/*
* @copyright 2012 Philip Warner
* @license GNU General Public License
*
* This file is part of Book Catalogue.
*
* Book Catalogue is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Book Catalogue is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Book Catalogue. If not, see <http://www.gnu.org/licenses/>.
*/
package com.eleybourn.bookcatalogue.booklist;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_ABSOLUTE_POSITION;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_AUTHOR_FORMATTED;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_AUTHOR_ID;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_BOOK;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_BOOK_UUID;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_FORMAT;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_GENRE;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_KIND;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_LEVEL;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_PUBLICATION_MONTH;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_READ;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_SERIES_ID;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_SERIES_NAME;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_SERIES_NUM;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_TITLE;
import static com.eleybourn.bookcatalogue.booklist.DatabaseDefinitions.DOM_TITLE_LETTER;
import android.content.res.Resources;
import android.database.Cursor;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import com.eleybourn.bookcatalogue.BookCatalogueApp;
import com.eleybourn.bookcatalogue.CatalogueDBAdapter;
import com.eleybourn.bookcatalogue.R;
import com.eleybourn.bookcatalogue.booklist.BooklistGroup.RowKinds;
import com.eleybourn.bookcatalogue.utils.Utils;
/**
* RowView object for the BooklistCursor.
*
* Implements methods to perform common tasks on the 'current' row of the cursor.
*
* @author Philip Warner
*/
public class BooklistRowView {
/** ID counter */
private static Integer mBooklistRowViewIdCounter = 0;
/** Underlying cursor */
private final Cursor mCursor;
/** Underlying builder object */
private final BooklistBuilder mBuilder;
/** Max size of thumbnails based on preferences at object creation time */
private final int mMaxThumbnailWidth;
/** Max size of thumbnails based on preferences at object creation time */
private final int mMaxThumbnailHeight;
/** Internal ID for this RowView */
private final long mId;
/**
* Constructor
*
* @param c Underlying Cursor
* @param builder Underlying Builder
*/
public BooklistRowView(BooklistCursor c, BooklistBuilder builder) {
// Allocate ID
synchronized(mBooklistRowViewIdCounter) {
mId = ++mBooklistRowViewIdCounter;
}
// Save underlying objects.
mCursor = c;
mBuilder = builder;
final int extras = mBuilder.getStyle().getExtras();
// Get thumbnail size
int maxSize = computeThumbnailSize(extras);
mMaxThumbnailWidth = maxSize;
mMaxThumbnailHeight = maxSize;
}
/**
* Constructor
*
* @param c Underlying Cursor
* @param builder Underlying Builder
*/
public BooklistRowView(BooklistPseudoCursor c, BooklistBuilder builder) {
// Allocate ID
synchronized(mBooklistRowViewIdCounter) {
mId = ++mBooklistRowViewIdCounter;
}
// Save underlying objects.
mCursor = c;
mBuilder = builder;
final int extras = mBuilder.getStyle().getExtras();
// Get thumbnail size
int maxSize = computeThumbnailSize(extras);
mMaxThumbnailWidth = maxSize;
mMaxThumbnailHeight = maxSize;
}
/**
* Return the thumbnail size in DP.
*
* @param extras Flags for style
*
* @return Requested thumbnail size
*/
private int computeThumbnailSize(int extras) {
int maxSize;
if ( (extras & BooklistStyle.EXTRAS_THUMBNAIL_LARGE) != 0) {
maxSize = 90;
} else {
maxSize = 60;
}
DisplayMetrics metrics = BookCatalogueApp.context.getResources().getDisplayMetrics();
maxSize = (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, maxSize, metrics));
return maxSize;
}
/**
* Get Utils from underlying cursor
*/
public Utils getUtils() {
return ((BooklistSupportProvider)mCursor).getUtils();
}
/**
* Accessor
*/
public BooklistStyle getStyle() {
return mBuilder.getStyle();
}
/**
* Accessor
*
* @return
*/
public long getId() {
return mId;
}
/**
* Accessor
*
* @return
*/
public int getMaxThumbnailHeight() {
return mMaxThumbnailHeight;
}
/**
* Accessor
*
* @return
*/
public int getMaxThumbnailWidth() {
return mMaxThumbnailWidth;
}
/**
* Checks if list displays series numbers anywhere.
*
* @return
*/
public boolean hasSeries() {
return hasColumn(CatalogueDBAdapter.KEY_SERIES_NUM);
}
/**
* Query underlying cursor for column index.
*
* @param columnName
* @return
*/
public int getColumnIndex(String columnName) {
return mCursor.getColumnIndex(columnName);
}
/**
* Get string from underlying cursor given a column index.
*
* @param columnIndex
* @return
*/
public String getString(int columnIndex) {
return mCursor.getString(columnIndex);
}
/**
* Get the text associated with the highest level group for the current item.
*/
private int mLevel1Col = -2;
public String getLevel1Data() {
if (mLevel1Col < 0) {
final String name = mBuilder.getDisplayDomain(1).name;
mLevel1Col = mCursor.getColumnIndex(name);
if (mLevel1Col < 0)
throw new RuntimeException("Column " + name + " not present in cursor");
}
return formatRowGroup(0, mCursor.getString(mLevel1Col));
}
/**
* Get the text associated with the second-highest level group for the current item.
*/
private int mLevel2Col = -2;
public String getLevel2Data() {
if (mBuilder.getStyle().size() < 2)
return null;
if (mLevel2Col < 0) {
final String name = mBuilder.getDisplayDomain(2).name;
mLevel2Col = mCursor.getColumnIndex(name);
if (mLevel2Col < 0)
throw new RuntimeException("Column " + name + " not present in cursor");
}
return formatRowGroup(1, mCursor.getString(mLevel2Col));
}
/**
* Perform any special formatting for a row group.
*
* @param level Level of the row group
* @param s Source value
* @return Formatted string
*/
private String formatRowGroup(int level, String s) {
switch(mBuilder.getStyle().getGroupAt(level).kind) {
case RowKinds.ROW_KIND_MONTH_ADDED:
case RowKinds.ROW_KIND_MONTH_PUBLISHED:
case RowKinds.ROW_KIND_MONTH_READ:
case RowKinds.ROW_KIND_UPDATE_MONTH:
try {
int i = Integer.parseInt(s);
// If valid, get the name
if (i > 0 && i <= 12) {
// Create static formatter if necessary
s = Utils.getMonthName(i);
}
} catch (Exception e) {
}
break;
case RowKinds.ROW_KIND_RATING:
try {
int i = Integer.parseInt(s);
// If valid, get the name
if (i >= 0 && i <= 5) {
Resources r = BookCatalogueApp.context.getResources();
s = r.getQuantityString(R.plurals.n_stars, i, i);
}
} catch (Exception e) {
}
break;
default:
break;
}
return s;
}
/**
* Check if a given column is present in underlying cursor.
*
* @param name
* @return
*/
public boolean hasColumn(String name) {
return mCursor.getColumnIndex(name) >= 0;
}
/**
* Get the 'absolute position' for the current row. This is a value
* generated by the builder object.
*/
private int mAbsPosCol = -2;
public int getAbsolutePosition() {
if (mAbsPosCol < 0) {
final String name = DOM_ABSOLUTE_POSITION.name;
mAbsPosCol = mCursor.getColumnIndex(name);
if (mAbsPosCol < 0)
throw new RuntimeException("Column " + name + " not present in cursor");
}
return mCursor.getInt(mAbsPosCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mBookIdCol = -2;
public long getBookId() {
if (mBookIdCol < 0) {
mBookIdCol = mCursor.getColumnIndex(DOM_BOOK.name);
if (mBookIdCol < 0)
throw new RuntimeException("Column " + DOM_BOOK + " not present in cursor");
}
return mCursor.getLong(mBookIdCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mBookUuidCol = -2;
public String getBookUuid() {
if (mBookUuidCol < 0) {
mBookUuidCol = mCursor.getColumnIndex(DOM_BOOK_UUID.name);
if (mBookUuidCol < 0)
throw new RuntimeException("Column " + DOM_BOOK_UUID + " not present in cursor");
}
return mCursor.getString(mBookUuidCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mSeriesIdCol = -2;
public long getSeriesId() {
if (mSeriesIdCol < 0) {
mSeriesIdCol = mCursor.getColumnIndex(DOM_SERIES_ID.name);
if (mSeriesIdCol < 0)
throw new RuntimeException("Column " + DOM_SERIES_ID + " not present in cursor");
}
return mCursor.getLong(mSeriesIdCol);
}
public boolean hasSeriesId() {
if (mSeriesIdCol >= 0)
return true;
mSeriesIdCol = mCursor.getColumnIndex(DOM_SERIES_ID.name);
return (mSeriesIdCol >= 0);
}
/**
* Convenience function to retrieve column value.
*/
private int mAuthorIdCol = -2;
public long getAuthorId() {
if (mAuthorIdCol < 0) {
mAuthorIdCol = mCursor.getColumnIndex(DOM_AUTHOR_ID.name);
if (mAuthorIdCol < 0)
throw new RuntimeException("Column " + DOM_AUTHOR_ID + " not present in cursor");
}
return mCursor.getLong(mAuthorIdCol);
}
public boolean hasAuthorId() {
if (mAuthorIdCol >= 0)
return true;
mAuthorIdCol = mCursor.getColumnIndex(DOM_AUTHOR_ID.name);
return (mAuthorIdCol >= 0);
}
/**
* Convenience function to retrieve column value.
*/
private int mKindCol = -2;
public int getKind() {
if (mKindCol < 0) {
mKindCol = mCursor.getColumnIndex(DOM_KIND.name);
if (mKindCol < 0)
throw new RuntimeException("Column " + DOM_KIND + " not present in cursor");
}
return mCursor.getInt(mKindCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mTitleCol = -2;
public String getTitle() {
if (mTitleCol < 0) {
mTitleCol = mCursor.getColumnIndex(DOM_TITLE.name);
if (mTitleCol < 0)
throw new RuntimeException("Column " + DOM_TITLE + " not present in cursor");
}
//System.out.println("BooklistRowView(" + mId + ") title at " + mTitleCol + " in cursor " + mCursor.getId());
return mCursor.getString(mTitleCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mPubMonthCol = -2;
public String getPublicationMonth() {
if (mPubMonthCol < 0) {
mPubMonthCol = mCursor.getColumnIndex(DOM_PUBLICATION_MONTH.name);
if (mPubMonthCol < 0)
throw new RuntimeException("Column " + DOM_PUBLICATION_MONTH + " not present in cursor");
}
return mCursor.getString(mPubMonthCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mAuthorCol = -2;
public String getAuthorName() {
if (mAuthorCol < 0) {
mAuthorCol = mCursor.getColumnIndex(DOM_AUTHOR_FORMATTED.name);
if (mAuthorCol < 0)
throw new RuntimeException("Column " + DOM_AUTHOR_FORMATTED + " not present in cursor");
}
return mCursor.getString(mAuthorCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mLevelCol = -2;
public int getLevel() {
if (mLevelCol < 0) {
mLevelCol = mCursor.getColumnIndex(DOM_LEVEL.name);
if (mLevelCol < 0)
throw new RuntimeException("Column " + DOM_LEVEL + " not present in cursor");
}
return mCursor.getInt(mLevelCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mFormatCol = -2;
public String getFormat() {
if (mFormatCol < 0) {
mFormatCol = mCursor.getColumnIndex(DOM_FORMAT.name);
if (mFormatCol < 0)
throw new RuntimeException("Column " + DOM_FORMAT + " not present in cursor");
}
return mCursor.getString(mFormatCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mGenreCol = -2;
public String getGenre() {
if (mGenreCol < 0) {
mGenreCol = mCursor.getColumnIndex(DOM_GENRE.name);
if (mGenreCol < 0)
throw new RuntimeException("Column " + DOM_GENRE + " not present in cursor");
}
return mCursor.getString(mGenreCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mTitleLetterCol = -2;
public String getTitleLetter() {
if (mTitleLetterCol < 0) {
mTitleLetterCol = mCursor.getColumnIndex(DOM_TITLE_LETTER.name);
if (mTitleLetterCol < 0)
throw new RuntimeException("Column " + DOM_TITLE_LETTER.name + " not present in cursor");
}
return mCursor.getString(mTitleLetterCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mSeriesNameCol = -2;
public String getSeriesName() {
if (mSeriesNameCol < 0) {
mSeriesNameCol = mCursor.getColumnIndex(DOM_SERIES_NAME.name);
if (mSeriesNameCol < 0)
throw new RuntimeException("Column " + DOM_SERIES_NAME + " not present in cursor");
}
return mCursor.getString(mSeriesNameCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mSeriesNumberCol = -2;
public String getSeriesNumber() {
if (mSeriesNumberCol < 0) {
mSeriesNumberCol = mCursor.getColumnIndex(DOM_SERIES_NUM.name);
if (mSeriesNumberCol < 0)
throw new RuntimeException("Column " + DOM_SERIES_NUM + " not present in cursor");
}
return mCursor.getString(mSeriesNumberCol);
}
/**
* Convenience function to retrieve column value.
*/
private int mReadCol = -2;
public boolean getRead() {
if (mReadCol < 0) {
mReadCol = mCursor.getColumnIndex(DOM_READ.name);
if (mReadCol < 0)
throw new RuntimeException("Column " + DOM_READ + " not present in cursor");
}
return mCursor.getLong(mReadCol) == 1;
}
}