11dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua/* 21dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * Copyright (C) 2012 The Android Open Source Project 31dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * 41dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * Licensed under the Apache License, Version 2.0 (the "License"); 51dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * you may not use this file except in compliance with the License. 61dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * You may obtain a copy of the License at 71dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * 81dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * http://www.apache.org/licenses/LICENSE-2.0 91dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * 101dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * Unless required by applicable law or agreed to in writing, software 111dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * distributed under the License is distributed on an "AS IS" BASIS, 121dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * See the License for the specific language governing permissions and 141dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua * limitations under the License. 151dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua */ 161dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 171dd8ef56681617db46caec7776c9bf416f01d8ddWei Huapackage android.bordeaux.services; 181dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 191dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport android.content.ContentValues; 201dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport android.content.Context; 211dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport android.database.Cursor; 221dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport android.database.SQLException; 231dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport android.database.sqlite.SQLiteDatabase; 241dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport android.database.sqlite.SQLiteOpenHelper; 251dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport android.util.Log; 261dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 271dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport java.lang.System; 281dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaimport java.util.concurrent.ConcurrentHashMap; 291dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 301dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua// This class manages the database for storing the session data. 311dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua// 321dd8ef56681617db46caec7776c9bf416f01d8ddWei Huaclass BordeauxSessionStorage { 331dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 341dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private static final String TAG = "BordeauxSessionStorage"; 351dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua // unique key for the session 361dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua public static final String COLUMN_KEY = "key"; 371dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua // name of the learning class 381dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua public static final String COLUMN_CLASS = "class"; 391dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua // data of the learning model 401dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua public static final String COLUMN_MODEL = "model"; 411dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua // last update time 421dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua public static final String COLUMN_TIME = "time"; 431dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 441dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private static final String DATABASE_NAME = "bordeaux"; 451dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private static final String SESSION_TABLE = "sessions"; 461dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private static final int DATABASE_VERSION = 1; 471dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private static final String DATABASE_CREATE = 481dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua "create table " + SESSION_TABLE + "( " + COLUMN_KEY + 491dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua " TEXT primary key, " + COLUMN_CLASS + " TEXT, " + 501dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua COLUMN_MODEL + " BLOB, " + COLUMN_TIME + " INTEGER);"; 511dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 521dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private SessionDBHelper mDbHelper; 531dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private SQLiteDatabase mDbSessions; 541dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 551dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua BordeauxSessionStorage(final Context context) { 561dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua try { 571dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua mDbHelper = new SessionDBHelper(context); 581dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua mDbSessions = mDbHelper.getWritableDatabase(); 591dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } catch (SQLException e) { 601dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua throw new RuntimeException("Can't open session database"); 611dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 621dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 631dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 641dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private class SessionDBHelper extends SQLiteOpenHelper { 651dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua SessionDBHelper(Context context) { 661dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua super(context, DATABASE_NAME, null, DATABASE_VERSION); 671dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 681dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 691dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua @Override 701dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua public void onCreate(SQLiteDatabase db) { 711dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua db.execSQL(DATABASE_CREATE); 721dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 731dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 741dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua @Override 751dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 761dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua Log.w(TAG, "Upgrading database from version " + oldVersion + " to " 771dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua + newVersion + ", which will destroy all old data"); 781dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 791dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua db.execSQL("DROP TABLE IF EXISTS " + SESSION_TABLE); 801dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua onCreate(db); 811dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 821dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 831dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 841dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private ContentValues createSessionEntry(String key, Class learner, byte[] model) { 851dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua ContentValues entry = new ContentValues(); 861dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua entry.put(COLUMN_KEY, key); 871dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua entry.put(COLUMN_TIME, System.currentTimeMillis()); 881dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua entry.put(COLUMN_MODEL, model); 891dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua entry.put(COLUMN_CLASS, learner.getName()); 901dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua return entry; 911dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 921dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 931dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua boolean saveSession(String key, Class learner, byte[] model) { 941dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua ContentValues content = createSessionEntry(key, learner, model); 951dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua long rowID = 961dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua mDbSessions.insertWithOnConflict(SESSION_TABLE, null, content, 971dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua SQLiteDatabase.CONFLICT_REPLACE); 981dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua return rowID >= 0; 991dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 1001dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 1011dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua private BordeauxSessionManager.Session getSessionFromCursor(Cursor cursor) { 1021dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua BordeauxSessionManager.Session session = new BordeauxSessionManager.Session(); 1031dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua String className = cursor.getString(cursor.getColumnIndex(COLUMN_CLASS)); 1041dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua try { 1051dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua session.learnerClass = Class.forName(className); 1061dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua session.learner = (IBordeauxLearner) session.learnerClass.getConstructor().newInstance(); 1071dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } catch (Exception e) { 1081dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua throw new RuntimeException("Can't instantiate class: " + className); 1091dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 1101dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua byte[] model = cursor.getBlob(cursor.getColumnIndex(COLUMN_MODEL)); 1111dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua session.learner.setModel(model); 1121dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua return session; 1131dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 1141dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 1151dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua BordeauxSessionManager.Session getSession(String key) { 1161dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua Cursor cursor = mDbSessions.query(true, SESSION_TABLE, 1171dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua new String[]{COLUMN_KEY, COLUMN_CLASS, COLUMN_MODEL, COLUMN_TIME}, 1181dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua COLUMN_KEY + "=\"" + key + "\"", null, null, null, null, null); 119984e52f31d596840cfa51b1238e1c43d2e1918f8saberian if ((cursor == null) | (cursor.getCount() == 0)) { 120984e52f31d596840cfa51b1238e1c43d2e1918f8saberian cursor.close(); 121984e52f31d596840cfa51b1238e1c43d2e1918f8saberian return null; 122984e52f31d596840cfa51b1238e1c43d2e1918f8saberian } 1231dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua if (cursor.getCount() > 1) { 124984e52f31d596840cfa51b1238e1c43d2e1918f8saberian cursor.close(); 1251dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua throw new RuntimeException("Unexpected duplication in session table for key:" + key); 1261dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 1271dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua cursor.moveToFirst(); 128984e52f31d596840cfa51b1238e1c43d2e1918f8saberian BordeauxSessionManager.Session s = getSessionFromCursor(cursor); 129984e52f31d596840cfa51b1238e1c43d2e1918f8saberian cursor.close(); 130984e52f31d596840cfa51b1238e1c43d2e1918f8saberian return s; 1311dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 1321dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 1331dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua void getAllSessions(ConcurrentHashMap<String, BordeauxSessionManager.Session> sessions) { 1341dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua Cursor cursor = mDbSessions.rawQuery("select * from ?;", new String[]{SESSION_TABLE}); 1351dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua if (cursor == null) return; 1362fc454f62ff5e11eb16a93a3d515a4e4fba89b5eWei Hua cursor.moveToFirst(); 1371dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua do { 1381dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua String key = cursor.getString(cursor.getColumnIndex(COLUMN_KEY)); 1391dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua BordeauxSessionManager.Session session = getSessionFromCursor(cursor); 1401dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua sessions.put(key, session); 1411dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } while (cursor.moveToNext()); 1421dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 1431dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua 1441dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua // remove all sessions that have the key that matches the given sql regular 1451dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua // expression. 1461dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua int removeSessions(String reKey) { 1471dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua int nDeleteRows = mDbSessions.delete(SESSION_TABLE, "? like \"?\"", 1481dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua new String[]{COLUMN_KEY, reKey}); 1491dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua Log.i(TAG, "Number of rows in session table deleted: " + nDeleteRows); 1501dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua return nDeleteRows; 1511dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua } 1521dd8ef56681617db46caec7776c9bf416f01d8ddWei Hua} 153