package com.quran.labs.androidquran.data; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.graphics.RectF; import android.support.annotation.NonNull; import com.quran.labs.androidquran.common.AyahBounds; import com.quran.labs.androidquran.database.DatabaseUtils; import com.quran.labs.androidquran.util.QuranFileUtils; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class AyahInfoDatabaseHandler { private static final String COL_PAGE = "page_number"; private static final String COL_LINE = "line_number"; private static final String COL_SURA = "sura_number"; private static final String COL_AYAH = "ayah_number"; private static final String COL_POSITION = "position"; private static final String MIN_X = "min_x"; private static final String MIN_Y = "min_y"; private static final String MAX_X = "max_x"; private static final String MAX_Y = "max_y"; private static final String GLYPHS_TABLE = "glyphs"; private static Map<String, AyahInfoDatabaseHandler> ayahInfoCache = new HashMap<>(); private final SQLiteDatabase database; static AyahInfoDatabaseHandler getAyahInfoDatabaseHandler(Context context, String databaseName) { AyahInfoDatabaseHandler handler = ayahInfoCache.get(databaseName); if (handler == null) { try { AyahInfoDatabaseHandler db = new AyahInfoDatabaseHandler(context, databaseName); if (db.validDatabase()) { ayahInfoCache.put(databaseName, db); handler = db; } } catch (SQLException sqlException) { // it's okay, we'll try again later } } return handler; } private AyahInfoDatabaseHandler(Context context, String databaseName) throws SQLException { String base = QuranFileUtils.getQuranAyahDatabaseDirectory(context); if (base == null) { database = null; } else { String path = base + File.separator + databaseName; database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); } } private boolean validDatabase() { return database != null && database.isOpen(); } @NonNull public RectF getPageBounds(int page) { Cursor c = null; try { String[] colNames = new String[]{ "MIN(" + MIN_X + ")", "MIN(" + MIN_Y + ")", "MAX(" + MAX_X + ")", "MAX(" + MAX_Y + ")" }; c = database.query(GLYPHS_TABLE, colNames, COL_PAGE + "=" + page, null, null, null, null); if (c.moveToFirst()) { return new RectF(c.getInt(0), c.getInt(1), c.getInt(2), c.getInt(3)); } else { throw new IllegalArgumentException("getPageBounds() on a non-existent page: " + page); } } finally { DatabaseUtils.closeCursor(c); } } @NonNull public Map<String, List<AyahBounds>> getVersesBoundsForPage(int page) { Map<String, List<AyahBounds>> result = new HashMap<>(); Cursor cursor = null; try { cursor = getVersesBoundsCursorForPage(page); while (cursor.moveToNext()) { int sura = cursor.getInt(2); int ayah = cursor.getInt(3); String key = sura + ":" + ayah; List<AyahBounds> bounds = result.get(key); if (bounds == null) { bounds = new ArrayList<>(); } AyahBounds last = null; if (bounds.size() > 0) { last = bounds.get(bounds.size() - 1); } AyahBounds bound = new AyahBounds(cursor.getInt(1), cursor.getInt(4), cursor.getInt(5), cursor.getInt(6), cursor.getInt(7), cursor.getInt(8)); if (last != null && last.getLine() == bound.getLine()) { last.engulf(bound); } else { bounds.add(bound); } result.put(key, bounds); } } finally { DatabaseUtils.closeCursor(cursor); } return result; } private Cursor getVersesBoundsCursorForPage(int page) { return database.query(GLYPHS_TABLE, new String[]{ COL_PAGE, COL_LINE, COL_SURA, COL_AYAH, COL_POSITION, MIN_X, MIN_Y, MAX_X, MAX_Y }, COL_PAGE + "=" + page, null, null, null, COL_SURA + "," + COL_AYAH + "," + COL_POSITION); } }