1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.bordeaux.services; 18 19import android.content.ContentValues; 20import android.content.Context; 21import android.database.Cursor; 22import android.database.SQLException; 23import android.database.sqlite.SQLiteDatabase; 24import android.database.sqlite.SQLiteOpenHelper; 25import android.util.Log; 26 27import java.lang.System; 28import java.util.concurrent.ConcurrentHashMap; 29 30// This class manages the database for storing the session data. 31// 32class BordeauxSessionStorage { 33 34 private static final String TAG = "BordeauxSessionStorage"; 35 // unique key for the session 36 public static final String COLUMN_KEY = "key"; 37 // name of the learning class 38 public static final String COLUMN_CLASS = "class"; 39 // data of the learning model 40 public static final String COLUMN_MODEL = "model"; 41 // last update time 42 public static final String COLUMN_TIME = "time"; 43 44 private static final String DATABASE_NAME = "bordeaux"; 45 private static final String SESSION_TABLE = "sessions"; 46 private static final int DATABASE_VERSION = 1; 47 private static final String DATABASE_CREATE = 48 "create table " + SESSION_TABLE + "( " + COLUMN_KEY + 49 " TEXT primary key, " + COLUMN_CLASS + " TEXT, " + 50 COLUMN_MODEL + " BLOB, " + COLUMN_TIME + " INTEGER);"; 51 52 private SessionDBHelper mDbHelper; 53 private SQLiteDatabase mDbSessions; 54 55 BordeauxSessionStorage(final Context context) { 56 try { 57 mDbHelper = new SessionDBHelper(context); 58 mDbSessions = mDbHelper.getWritableDatabase(); 59 } catch (SQLException e) { 60 throw new RuntimeException("Can't open session database"); 61 } 62 } 63 64 private class SessionDBHelper extends SQLiteOpenHelper { 65 SessionDBHelper(Context context) { 66 super(context, DATABASE_NAME, null, DATABASE_VERSION); 67 } 68 69 @Override 70 public void onCreate(SQLiteDatabase db) { 71 db.execSQL(DATABASE_CREATE); 72 } 73 74 @Override 75 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 76 Log.w(TAG, "Upgrading database from version " + oldVersion + " to " 77 + newVersion + ", which will destroy all old data"); 78 79 db.execSQL("DROP TABLE IF EXISTS " + SESSION_TABLE); 80 onCreate(db); 81 } 82 } 83 84 private ContentValues createSessionEntry(String key, Class learner, byte[] model) { 85 ContentValues entry = new ContentValues(); 86 entry.put(COLUMN_KEY, key); 87 entry.put(COLUMN_TIME, System.currentTimeMillis()); 88 entry.put(COLUMN_MODEL, model); 89 entry.put(COLUMN_CLASS, learner.getName()); 90 return entry; 91 } 92 93 boolean saveSession(String key, Class learner, byte[] model) { 94 ContentValues content = createSessionEntry(key, learner, model); 95 long rowID = 96 mDbSessions.insertWithOnConflict(SESSION_TABLE, null, content, 97 SQLiteDatabase.CONFLICT_REPLACE); 98 return rowID >= 0; 99 } 100 101 private BordeauxSessionManager.Session getSessionFromCursor(Cursor cursor) { 102 BordeauxSessionManager.Session session = new BordeauxSessionManager.Session(); 103 String className = cursor.getString(cursor.getColumnIndex(COLUMN_CLASS)); 104 try { 105 session.learnerClass = Class.forName(className); 106 session.learner = (IBordeauxLearner) session.learnerClass.getConstructor().newInstance(); 107 } catch (Exception e) { 108 throw new RuntimeException("Can't instantiate class: " + className); 109 } 110 byte[] model = cursor.getBlob(cursor.getColumnIndex(COLUMN_MODEL)); 111 session.learner.setModel(model); 112 return session; 113 } 114 115 BordeauxSessionManager.Session getSession(String key) { 116 Cursor cursor = mDbSessions.query(true, SESSION_TABLE, 117 new String[]{COLUMN_KEY, COLUMN_CLASS, COLUMN_MODEL, COLUMN_TIME}, 118 COLUMN_KEY + "=\"" + key + "\"", null, null, null, null, null); 119 if ((cursor == null) | (cursor.getCount() == 0)) { 120 cursor.close(); 121 return null; 122 } 123 if (cursor.getCount() > 1) { 124 cursor.close(); 125 throw new RuntimeException("Unexpected duplication in session table for key:" + key); 126 } 127 cursor.moveToFirst(); 128 BordeauxSessionManager.Session s = getSessionFromCursor(cursor); 129 cursor.close(); 130 return s; 131 } 132 133 void getAllSessions(ConcurrentHashMap<String, BordeauxSessionManager.Session> sessions) { 134 Cursor cursor = mDbSessions.rawQuery("select * from ?;", new String[]{SESSION_TABLE}); 135 if (cursor == null) return; 136 cursor.moveToFirst(); 137 do { 138 String key = cursor.getString(cursor.getColumnIndex(COLUMN_KEY)); 139 BordeauxSessionManager.Session session = getSessionFromCursor(cursor); 140 sessions.put(key, session); 141 } while (cursor.moveToNext()); 142 } 143 144 // remove all sessions that have the key that matches the given sql regular 145 // expression. 146 int removeSessions(String reKey) { 147 int nDeleteRows = mDbSessions.delete(SESSION_TABLE, "? like \"?\"", 148 new String[]{COLUMN_KEY, reKey}); 149 Log.i(TAG, "Number of rows in session table deleted: " + nDeleteRows); 150 return nDeleteRows; 151 } 152} 153