Revision: 871
http://swingme.svn.sourceforge.net/swingme/?rev=871&view=rev
Author: janeroski
Date: 2010-05-04 15:45:21 +0000 (Tue, 04 May 2010)
Log Message:
-----------
RMS: Use SQLlite instead of File System (v0.1)
Modified Paths:
--------------
AndroidME/src_MIDP/javax/microedition/rms/RecordStore.java
Added Paths:
-----------
AndroidME/src_Android/net/yura/android/rms/SqlDao.java
AndroidME/src_Android/net/yura/android/rms/SqlRecordEnumeration.java
Removed Paths:
-------------
AndroidME/src_Android/net/yura/android/rms/RecordEnumerationImpl.java
Deleted: AndroidME/src_Android/net/yura/android/rms/RecordEnumerationImpl.java
===================================================================
--- AndroidME/src_Android/net/yura/android/rms/RecordEnumerationImpl.java 2010-05-04 13:38:37 UTC (rev 870)
+++ AndroidME/src_Android/net/yura/android/rms/RecordEnumerationImpl.java 2010-05-04 15:45:21 UTC (rev 871)
@@ -1,265 +0,0 @@
-/*
- * MicroEmulator
- * Copyright (C) 2001-2005 Bartek Teodorczyk <ba...@ba...>
- *
- * It is licensed under the following two licenses as alternatives:
- * 1. GNU Lesser General Public License (the "LGPL") version 2.1 or any newer version
- * 2. Apache License (the "AL") Version 2.0
- *
- * You may not use this file except in compliance with at least one of
- * the above two licenses.
- *
- * You may obtain a copy of the LGPL at
- * http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
- *
- * You may obtain a copy of the AL 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 LGPL or the AL for the specific language governing permissions and
- * limitations.
- */
-
-package net.yura.android.rms;
-
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Enumeration;
-import java.util.Vector;
-
-import javax.microedition.rms.InvalidRecordIDException;
-import javax.microedition.rms.RecordComparator;
-import javax.microedition.rms.RecordEnumeration;
-import javax.microedition.rms.RecordFilter;
-import javax.microedition.rms.RecordListener;
-import javax.microedition.rms.RecordStore;
-import javax.microedition.rms.RecordStoreException;
-import javax.microedition.rms.RecordStoreNotOpenException;
-
-
-public class RecordEnumerationImpl implements RecordEnumeration
-{
- private RecordStore recordStore;
- private RecordFilter filter;
- private RecordComparator comparator;
- private boolean keepUpdated;
-
- private Vector enumerationRecords = new Vector();
- private int currentRecord;
-
- private RecordListener recordListener = new RecordListener()
- {
-
- public void recordAdded(RecordStore recordStore, int recordId) {
- rebuild();
- }
-
- public void recordChanged(RecordStore recordStore, int recordId) {
- rebuild();
- }
-
- public void recordDeleted(RecordStore recordStore, int recordId) {
- rebuild();
- }
-
- };
-
-
- public RecordEnumerationImpl(RecordStore recordStore, RecordFilter filter, RecordComparator comparator, boolean keepUpdated)
- {
- this.recordStore = recordStore;
- this.filter = filter;
- this.comparator = comparator;
- this.keepUpdated = keepUpdated;
-
- rebuild();
-
- if (keepUpdated) {
- recordStore.addRecordListener(recordListener);
- }
- }
-
-
- public int numRecords()
- {
- return enumerationRecords.size();
- }
-
-
- public byte[] nextRecord()
- throws InvalidRecordIDException, RecordStoreNotOpenException, RecordStoreException
- {
- if (!recordStore.isOpen()) {
- throw new RecordStoreNotOpenException();
- }
-
- if (currentRecord >= numRecords()) {
- throw new InvalidRecordIDException();
- }
-
- byte[] result = ((EnumerationRecord) enumerationRecords
- .elementAt(currentRecord)).value;
- currentRecord++;
-
- return result;
- }
-
-
- public int nextRecordId()
- throws InvalidRecordIDException
- {
- if (currentRecord >= numRecords()) {
- throw new InvalidRecordIDException();
- }
-
- int result = ((EnumerationRecord) enumerationRecords
- .elementAt(currentRecord)).recordId;
- currentRecord++;
-
- return result;
- }
-
-
- public byte[] previousRecord()
- throws InvalidRecordIDException, RecordStoreNotOpenException, RecordStoreException
- {
- if (!recordStore.isOpen()) {
- throw new RecordStoreNotOpenException();
- }
- if (currentRecord < 0) {
- throw new InvalidRecordIDException();
- }
-
- byte[] result = ((EnumerationRecord) enumerationRecords
- .elementAt(currentRecord)).value;
- currentRecord--;
-
- return result;
- }
-
-
- public int previousRecordId()
- throws InvalidRecordIDException
- {
- if (currentRecord < 0) {
- throw new InvalidRecordIDException();
- }
-
- int result = ((EnumerationRecord) enumerationRecords
- .elementAt(currentRecord)).recordId;
- currentRecord--;
-
- return result;
- }
-
-
- public boolean hasNextElement()
- {
- if (currentRecord == numRecords()) {
- return false;
- } else {
- return true;
- }
- }
-
-
- public boolean hasPreviousElement()
- {
- if (currentRecord == 0) {
- return false;
- } else {
- return true;
- }
- }
-
-
- public void reset()
- {
- currentRecord = 0;
- }
-
-
- public void rebuild()
- {
- enumerationRecords.removeAllElements();
-
- //
- // filter
- //
- for (Enumeration e = recordStore.records.keys(); e.hasMoreElements();) {
- Object key = e.nextElement();
- byte[] data = (byte[]) recordStore.records.get(key);
- if (filter != null && !filter.matches(data)) {
- continue;
- }
- enumerationRecords.add(new EnumerationRecord( ((Integer) key).intValue(),
- data));
- }
-
- //
- // sort
- //
- if (comparator != null) {
- Collections.sort(enumerationRecords, new Comparator() {
-
- public int compare(Object lhs, Object rhs) {
-
- int compare = comparator.compare(((EnumerationRecord) lhs).value,
- ((EnumerationRecord) rhs).value);
- if (compare == RecordComparator.EQUIVALENT)
- return 0;
- else if (compare == RecordComparator.FOLLOWS)
- return 1;
- else
- return -1;
-
- }
-
- });
- }
- }
-
-
- public void keepUpdated(boolean keepUpdated)
- {
- if (keepUpdated) {
- if (!this.keepUpdated) {
- rebuild();
- recordStore.addRecordListener(recordListener);
- }
- } else {
- recordStore.removeRecordListener(recordListener);
- }
-
- this.keepUpdated = keepUpdated;
- }
-
-
- public boolean isKeptUpdated()
- {
- return keepUpdated;
- }
-
-
- public void destroy()
- {
- }
-
-
- class EnumerationRecord
- {
- int recordId;
-
- byte[] value;
-
-
- EnumerationRecord(int recordId, byte[] value)
- {
- this.recordId = recordId;
- this.value = value;
- }
- }
-
-}
Added: AndroidME/src_Android/net/yura/android/rms/SqlDao.java
===================================================================
--- AndroidME/src_Android/net/yura/android/rms/SqlDao.java (rev 0)
+++ AndroidME/src_Android/net/yura/android/rms/SqlDao.java 2010-05-04 15:45:21 UTC (rev 871)
@@ -0,0 +1,392 @@
+package net.yura.android.rms;
+
+import javax.microedition.rms.RecordStore;
+import javax.microedition.rms.RecordStoreException;
+import javax.microedition.rms.RecordStoreNotFoundException;
+
+import net.yura.android.AndroidMeMIDlet;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.database.sqlite.SQLiteDatabase.CursorFactory;
+
+/**
+ * This DAO manages one database. It is a singleton and is only valid for one application.
+ * TODO: How to close the database? Is there a close hook?
+ * @author rickyn
+ *
+ */
+public class SqlDao {
+
+ private final class RecordStoreSqliteOpenHelper extends SQLiteOpenHelper {
+
+ RecordStoreSqliteOpenHelper(Context context, String name,
+ CursorFactory factory, int version) {
+ super(context, name, factory, version);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase database2) {
+ // Version 1.
+ // TODO: Add upgrade mechanism to add a size field in the Record table.
+ // TODO: Add an index to the tables. Check if it is needed for the PK.
+ String a = "CREATE TABLE "+TABLENAME_RECORDSTORE+" (" +
+ COLUMNNAME_RECORDSTORE_RECORDSTORE_PK + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
+ COLUMNNAME_RECORDSTORE_NAME + " VARCHAR(30) NOT NULL," +
+ COLUMNNAME_RECORDSTORE_SIZE+" INT DEFAULT 0," +
+ COLUMNNAME_RECORDSTORE_NEXTID+" INT DEFAULT 1," +
+ "auth_mode INT DEFAULT 0," +
+ "writeable TINYINT(1) DEFAULT 0," +
+ COLUMNNAME_RECORDSTORE_VERSION + " INT DEFAULT 0," +
+ COLUMNNAME_RECORDSTORE_NUMBER_OF_RECORDS + " INT DEFAULT 0," +
+ "timestamp INT DEFAULT 0);";
+ String b = "CREATE TABLE " + TABLENAME_RECORD + " (" +
+ COLUMNNAME_RECORD_RECORD_PK + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
+ COLUMNNAME_RECORD_RECORDSTORE_FK + " INT NOT NULL," +
+ COLUMNNAME_RECORD_DATA + " BLOB," +
+ COLUMNNAME_RECORD_RECORDNUMBER + " INT NOT NULL);";
+ database2.beginTransaction();
+ database2.execSQL(a);
+ database2.execSQL(b);
+ database2.setTransactionSuccessful();
+ database2.endTransaction();
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
+ //#debug
+ System.out.println("ERROR:Call to RecordStoreSqliteOpenHelper.onUpgrade not implemented. arg1:"+arg1+". arg2:"+arg2);
+ }
+ }
+
+ public static final String TABLENAME_RECORDSTORE = "recordstore";
+ public static final String COLUMNNAME_RECORDSTORE_RECORDSTORE_PK = "recordstore_pk";
+ public static final String COLUMNNAME_RECORDSTORE_NAME = "name";
+ public static final String COLUMNNAME_RECORDSTORE_VERSION = "version";
+ public static final String COLUMNNAME_RECORDSTORE_NEXTID = "nextId";
+ public static final String COLUMNNAME_RECORDSTORE_NUMBER_OF_RECORDS = "number_of_records";
+ public static final String COLUMNNAME_RECORDSTORE_SIZE = "current_size";
+
+ public static final String TABLENAME_RECORD = "record";
+ public static final String COLUMNNAME_RECORD_RECORD_PK = "record_pk";
+ public static final String COLUMNNAME_RECORD_RECORDSTORE_FK = "recordstore_fk";
+ // The number of the record. It is used by the API
+ public static final String COLUMNNAME_RECORD_RECORDNUMBER = "record_number";
+ public static final String COLUMNNAME_RECORD_DATA = "bytes";
+
+ private static SQLiteDatabase database;
+ private static SqlDao instance;
+
+ private SqlDao() {
+ init();
+ }
+
+ public static SqlDao getInstance() {
+ // Do not make a static initialization as we need a context. We have to test at which point in the startup process the context is available.
+ if(instance == null) {
+ instance = new SqlDao();
+ }
+ return instance;
+ }
+
+ /**
+ * Get the record store with the given name from the database.
+ * @param recordStoreName The name of the record store. Must not be null.
+ * @return An RecordStore object or null if the record store could not be found.
+ */
+ public synchronized RecordStore getRecordStore(String recordStoreName) {
+ if(recordStoreName == null) {
+ throw new IllegalArgumentException("The parameter 'recordStoreName' must not be null.");
+ }
+ Cursor resultCursor = database.query(SqlDao.TABLENAME_RECORDSTORE, null, "name = ?", new String[] {recordStoreName}, null, null, null);
+ RecordStore recordStore;
+ try {
+ if(resultCursor.getCount() == 0) {
+ return null;
+ }
+ recordStore = extractRecordStore(resultCursor);
+ } finally {
+ resultCursor.close();
+ }
+ return recordStore;
+ }
+
+ public synchronized RecordStore getRecordStore(long pk) {
+ if(pk < 0) {
+ throw new IllegalArgumentException("The parameter 'recordStoreName' must not have a negative value.");
+ }
+ Cursor result;
+ RecordStore recordStore;
+ result = database.query(SqlDao.TABLENAME_RECORDSTORE, null, COLUMNNAME_RECORDSTORE_RECORDSTORE_PK+" = ?", new String[] {pk+""}, null, null, null);
+ try {
+ if(result.getCount() == 0) {
+ return null;
+ }
+ recordStore = extractRecordStore(result);
+ } finally {
+ result.close();
+ }
+ return recordStore;
+ }
+
+ /**
+ * This methods extracts a RecordStore object from the database cursor. This method will not close this cursor, the caller is responsible for it.
+ * @param result A Cursor object which is not closed and will not be closed by this method.
+ * @return
+ */
+ private synchronized RecordStore extractRecordStore(Cursor result) {
+ result.moveToFirst();
+ int indexOfColumn;
+ indexOfColumn = result.getColumnIndex(SqlDao.COLUMNNAME_RECORDSTORE_RECORDSTORE_PK);
+ int id = result.getInt(indexOfColumn);
+
+ indexOfColumn = result.getColumnIndex(SqlDao.COLUMNNAME_RECORDSTORE_VERSION);
+ int version = result.getInt(indexOfColumn);
+
+ indexOfColumn = result.getColumnIndex(SqlDao.COLUMNNAME_RECORDSTORE_NEXTID);
+ int nextId = result.getInt(indexOfColumn);
+
+ indexOfColumn = result.getColumnIndex(SqlDao.COLUMNNAME_RECORDSTORE_NAME);
+ String recordStoreName = result.getString(indexOfColumn);
+
+ indexOfColumn = result.getColumnIndex(SqlDao.COLUMNNAME_RECORDSTORE_NUMBER_OF_RECORDS);
+ int numberOfRecords = result.getInt(indexOfColumn);
+
+ indexOfColumn = result.getColumnIndex(SqlDao.COLUMNNAME_RECORDSTORE_SIZE);
+ int size = result.getInt(indexOfColumn);
+
+ RecordStore recordStore = new RecordStore(recordStoreName,id);
+ recordStore.setVersion(version);
+ recordStore.setNextId(nextId);
+ recordStore.setNumberOfRecords(numberOfRecords);
+ recordStore.setSize(size);
+
+ return recordStore;
+ }
+
+ /**
+ * Creates a record store entry in the database.
+ * @param recordStoreName The name of the record store to be created. The name must be unique. The value must not be null.
+ * @return A RecordStore object.
+ * @throws RecordStoreException
+ * @throws DaoException In case anything goes wrong. This situation is fatal.
+ */
+ public synchronized RecordStore createRecordStore(String recordStoreName) throws RecordStoreException {
+ if(recordStoreName == null) {
+ throw new IllegalArgumentException("The parameter 'recordStoreName' must not be null.");
+ }
+ ContentValues values = new ContentValues();
+ values.put(COLUMNNAME_RECORDSTORE_NAME, recordStoreName);
+ long id;
+ try {
+ database.beginTransaction();
+ id = database.insertOrThrow(SqlDao.TABLENAME_RECORDSTORE, null, values);
+ database.setTransactionSuccessful();
+ database.endTransaction();
+ } catch (SQLException e) {
+ throw new RecordStoreException("Could not insert record store row with name '"+recordStoreName+"'. Reason: "+e);
+ }
+ if(id == -1) {
+ throw new RecordStoreException("Could not insert record store row with name '"+recordStoreName+"'. Reason: The method 'SQLiteDatabase.insertOrThrow' returned '-1' instead of throwing an exception.");
+ }
+ RecordStore recordStore = new RecordStore(recordStoreName,id);
+ return recordStore;
+ }
+
+ private void init() {
+ Context context = AndroidMeMIDlet.DEFAULT_ACTIVITY;
+ SQLiteOpenHelper recordStoreSqliteOpenHelper = new RecordStoreSqliteOpenHelper(context, "recordstoredb", null, 3);
+ database = recordStoreSqliteOpenHelper.getWritableDatabase();
+ }
+
+ public synchronized void destroy() {
+ database.close();
+ }
+
+ public synchronized String[] listRecordStores() {
+ Cursor resultCursor = database.query(TABLENAME_RECORDSTORE, new String[] {COLUMNNAME_RECORDSTORE_NAME}, null, null, null, null,null);
+ String[] recordStores;
+ try {
+ int numberOfRecordStores = resultCursor.getCount();
+ recordStores = new String[numberOfRecordStores];
+ for (int i = 0; i < numberOfRecordStores; i++) {
+ resultCursor.move(1);
+ recordStores[i] = resultCursor.getString(0);
+ }
+ } finally {
+ resultCursor.close();
+ }
+ return recordStores;
+ }
+
+ public synchronized void deleteRecordStore(String recordStoreName) throws RecordStoreNotFoundException {
+ RecordStore recordStore = getRecordStore(recordStoreName);
+ if(recordStore == null) {
+ throw new RecordStoreNotFoundException("Could not delete row in table '"+TABLENAME_RECORDSTORE+"' with value '"+recordStoreName+"'");
+ }
+ database.beginTransaction();
+ database.delete(TABLENAME_RECORDSTORE, "name = ?", new String[]{recordStoreName});
+ database.delete(TABLENAME_RECORD, COLUMNNAME_RECORD_RECORDSTORE_FK+" = ?", new String[]{Long.toString(recordStore.getPk())});
+ database.setTransactionSuccessful();
+ database.endTransaction();
+ }
+
+ /**
+ *
+ * @param recordStoreFk the primary key of the recordstore this record is created in. This value must be valid as it is not cheched.
+ * @param data Must not be null.
+ * @return the id of the added record
+ * @throws RecordStoreException
+ */
+ public synchronized int addRecord(long recordStoreFk, byte[] data) throws RecordStoreException {
+ Cursor result = database.query(SqlDao.TABLENAME_RECORDSTORE, null, COLUMNNAME_RECORDSTORE_RECORDSTORE_PK+" = ?", new String[] {recordStoreFk+""}, null, null, null);
+ int version;
+ int nextRecordId;
+ int numberOfRecords;
+ int size;
+ try {
+ result.moveToFirst();
+ int indexOfColumn;
+ indexOfColumn = result.getColumnIndex(SqlDao.COLUMNNAME_RECORDSTORE_VERSION);
+ version = result.getInt(indexOfColumn);
+
+ indexOfColumn = result.getColumnIndex(SqlDao.COLUMNNAME_RECORDSTORE_NEXTID);
+ nextRecordId = result.getInt(indexOfColumn);
+
+ indexOfColumn = result.getColumnIndex(SqlDao.COLUMNNAME_RECORDSTORE_NUMBER_OF_RECORDS);
+ numberOfRecords = result.getInt(indexOfColumn);
+
+ indexOfColumn = result.getColumnIndex(SqlDao.COLUMNNAME_RECORDSTORE_SIZE);
+ size = result.getInt(indexOfColumn);
+ } finally {
+ result.close();
+ }
+
+ // Insert record.
+ ContentValues values;
+ values = new ContentValues();
+ values.put(COLUMNNAME_RECORD_DATA, data);
+ values.put(COLUMNNAME_RECORD_RECORDNUMBER, new Integer(nextRecordId));
+ values.put(COLUMNNAME_RECORD_RECORDSTORE_FK, new Long(recordStoreFk));
+ try {
+ database.beginTransaction();
+ database.insertOrThrow(TABLENAME_RECORD, null, values);
+ database.setTransactionSuccessful();
+ database.endTransaction();
+ } catch (SQLException e) {
+ throw new RecordStoreException(e.toString());
+ }
+
+ // Update record store stats.
+ values.clear();
+ int newVersion = version + 1;
+ int newNextId = nextRecordId + 1;
+ int newNumberOfRecords = numberOfRecords + 1;
+ int recordStoreSize = size + data.length;
+ values.put(COLUMNNAME_RECORDSTORE_VERSION, new Integer(newVersion));
+ values.put(COLUMNNAME_RECORDSTORE_NEXTID, new Integer(newNextId));
+ values.put(COLUMNNAME_RECORDSTORE_NUMBER_OF_RECORDS, new Integer(newNumberOfRecords));
+ values.put(COLUMNNAME_RECORDSTORE_SIZE, new Integer(recordStoreSize));
+ try {
+ database.beginTransaction();
+ database.update(TABLENAME_RECORDSTORE, values, COLUMNNAME_RECORDSTORE_RECORDSTORE_PK + "= ?" , new String[] {Long.toString(recordStoreFk)});
+ database.setTransactionSuccessful();
+ database.endTransaction();
+ } catch (Exception e) {
+ throw new RecordStoreException(e.toString());
+ }
+ return nextRecordId;
+
+ }
+
+ /**
+ * @param recordStorePk
+ * @param recordId
+ * @return the data, or null
+ */
+ public synchronized byte[] getRecord(long recordStorePk, int recordId) {
+ Cursor resultCursor = database.query(TABLENAME_RECORD,new String[] {COLUMNNAME_RECORD_DATA},COLUMNNAME_RECORD_RECORDNUMBER+"=? AND "+COLUMNNAME_RECORD_RECORDSTORE_FK+"=?",new String[] {Long.toString(recordId),Long.toString(recordStorePk)},null,null,null);
+ byte[] data;
+ try {
+ if(resultCursor.getCount() == 0) {
+ return null;
+ }
+ resultCursor.moveToFirst();
+ data = resultCursor.getBlob(0);
+ } finally {
+ resultCursor.close();
+ }
+ return data;
+ }
+
+ /**
+ *
+ * @param recordStorePk
+ * @param recordId
+ * @param data Must not be null.
+ * @throws RecordStoreException
+ */
+ public synchronized void setRecord(long recordStorePk, int recordId, byte[] data) throws RecordStoreException {
+ ContentValues values = new ContentValues();
+ values.put(COLUMNNAME_RECORD_DATA, data);
+ try {
+ database.beginTransaction();
+ database.update(TABLENAME_RECORD, values, COLUMNNAME_RECORD_RECORDSTORE_FK + "= ? AND "+COLUMNNAME_RECORD_RECORDNUMBER+"=?" , new String[] {Long.toString(recordStorePk),Integer.toString(recordId)});
+ database.setTransactionSuccessful();
+ database.endTransaction();
+ } catch (Exception e) {
+ throw new RecordStoreException(e.toString());
+ }
+ RecordStore recordStore = getRecordStore(recordStorePk);
+ byte[] oldData = getRecord(recordStorePk,recordId);
+ values.clear();
+ int size = recordStore.getSize() + - oldData.length + data.length;
+ int version = recordStore.getVersion() + 1;
+ values.put(COLUMNNAME_RECORDSTORE_SIZE, new Integer(size));
+ values.put(COLUMNNAME_RECORDSTORE_VERSION, new Integer(version));
+ database.update(TABLENAME_RECORDSTORE, values, COLUMNNAME_RECORDSTORE_RECORDSTORE_PK + "= ?" , new String[] {Long.toString(recordStorePk)});
+ }
+
+ public synchronized void removeRecord(long recordStorePk, int recordId) throws RecordStoreException {
+ //TODO: Update the size in the recordstore table.
+ //TODO: Cache the size in the record table.
+ RecordStore recordStore = getRecordStore(recordStorePk);
+ byte[] oldData = getRecord(recordStorePk,recordId);
+ ContentValues values = new ContentValues();
+ int size = recordStore.getSize() - oldData.length;
+ int version = recordStore.getVersion() + 1;
+ values.put(COLUMNNAME_RECORDSTORE_SIZE, new Integer(size));
+ values.put(COLUMNNAME_RECORDSTORE_VERSION, new Integer(version));
+ database.update(TABLENAME_RECORDSTORE, values, COLUMNNAME_RECORDSTORE_RECORDSTORE_PK + "= ?" , new String[] {Long.toString(recordStorePk)});
+ database.delete(TABLENAME_RECORD,COLUMNNAME_RECORD_RECORDNUMBER+"=? AND "+COLUMNNAME_RECORD_RECORDSTORE_FK+"=?",new String[] {Integer.toString(recordId),Long.toString(recordStorePk)});
+ }
+
+ public synchronized int[] getRecordIdsForRecordStore(long recordStorePk) {
+ Cursor resultCursor = database.query(TABLENAME_RECORD,new String[] {COLUMNNAME_RECORD_RECORDNUMBER},COLUMNNAME_RECORD_RECORDSTORE_FK+"=?",new String[] {Long.toString(recordStorePk)},null,null,COLUMNNAME_RECORD_RECORDNUMBER+" ASC");
+ int[] result;
+ try {
+ int numberOfRecords = resultCursor.getCount();
+ if(numberOfRecords == 0) {
+ return new int[0];
+ }
+ resultCursor.moveToFirst();
+ result = new int[numberOfRecords];
+ for (int i = 0; i < numberOfRecords; i++) {
+ result[i] = resultCursor.getInt(0);
+ resultCursor.moveToNext();
+ }
+ } finally {
+ resultCursor.close();
+ }
+ return result;
+ }
+
+ // TODO: Implement this methods so we save expensive getRecord calls when updating the size in the methods setRecord and removeRecord.
+ public synchronized int getRecordSize() {
+ return 0;
+ }
+}
Added: AndroidME/src_Android/net/yura/android/rms/SqlRecordEnumeration.java
===================================================================
--- AndroidME/src_Android/net/yura/android/rms/SqlRecordEnumeration.java (rev 0)
+++ AndroidME/src_Android/net/yura/android/rms/SqlRecordEnumeration.java 2010-05-04 15:45:21 UTC (rev 871)
@@ -0,0 +1,193 @@
+//#condition polish.android
+package net.yura.android.rms;
+
+import javax.microedition.rms.InvalidRecordIDException;
+import javax.microedition.rms.RecordComparator;
+import javax.microedition.rms.RecordEnumeration;
+import javax.microedition.rms.RecordFilter;
+import javax.microedition.rms.RecordStore;
+import javax.microedition.rms.RecordStoreException;
+import javax.microedition.rms.RecordStoreNotOpenException;
+
+public class SqlRecordEnumeration implements RecordEnumeration{
+
+ private final RecordStore recordStore;
+ private final RecordFilter filter;
+ private final RecordComparator comparator;
+ private boolean keepUpdated;
+ private int lastRecordIndex;
+ private boolean destroyed = false;
+ private SqlDao sqlDao;
+ private int[] recordIds;
+
+ public SqlRecordEnumeration(RecordStore recordStore, RecordFilter filter, RecordComparator comparator, boolean keepUpdated) {
+ this.recordStore = recordStore;
+ this.filter = filter;
+ this.comparator = comparator;
+ this.keepUpdated = keepUpdated;
+ this.sqlDao = SqlDao.getInstance();
+ rebuild();
+ }
+
+ public void destroy() {
+ this.destroyed = true;
+ }
+
+ public boolean hasNextElement() {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ boolean hasNext = this.lastRecordIndex < this.recordIds.length-1;
+ return hasNext;
+ }
+
+ public boolean hasPreviousElement() {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ boolean hasPrevious = this.lastRecordIndex > 0;
+ return hasPrevious;
+ }
+
+ public boolean isKeptUpdated() {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ return this.keepUpdated;
+ }
+
+ public void keepUpdated(boolean keepUpdated2) {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ this.keepUpdated = keepUpdated2;
+ }
+
+ public byte[] nextRecord() throws InvalidRecordIDException,RecordStoreNotOpenException, RecordStoreException {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ if(this.recordStore.isClosed()) {
+ throw new RecordStoreNotOpenException("The record store which is enumerated is closed.");
+ }
+ int nextRecordIndex = this.lastRecordIndex + 1;
+ if(nextRecordIndex >= this.recordIds.length) {
+ throw new InvalidRecordIDException("The end of the enumeration is reached.");
+ }
+ this.lastRecordIndex = nextRecordIndex;
+ int recordId = this.recordIds[nextRecordIndex];
+ byte[] result = this.sqlDao.getRecord(this.recordStore.getPk(),recordId);
+ return result;
+ }
+
+ public int nextRecordId() throws InvalidRecordIDException {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ int nextRecordIndex = this.lastRecordIndex + 1;
+ if(nextRecordIndex >= this.recordIds.length) {
+ throw new InvalidRecordIDException("No more records in this enumeration.");
+ }
+ this.lastRecordIndex = nextRecordIndex;
+ int nextRecordId = this.recordIds[nextRecordIndex];
+ return nextRecordId;
+ }
+
+ public int numRecords() {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ return this.recordIds.length;
+ }
+
+ public byte[] previousRecord() throws InvalidRecordIDException, RecordStoreNotOpenException, RecordStoreException {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ if(this.recordStore.isClosed()) {
+ throw new RecordStoreNotOpenException("The record store which is enumerated is closed.");
+ }
+ int previousRecordIndex = this.lastRecordIndex - 1;
+ if(previousRecordIndex < 0) {
+ throw new InvalidRecordIDException("The start of the enumeration is reached.");
+ }
+ this.lastRecordIndex = previousRecordIndex;
+ int recordId = this.recordIds[previousRecordIndex];
+ byte[] result = this.sqlDao.getRecord(this.recordStore.getPk(),recordId);
+ return result;
+ }
+
+ public int previousRecordId() throws InvalidRecordIDException {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ int previousIndex = this.lastRecordIndex - 1;
+ if(this.lastRecordIndex < 0) {
+ throw new InvalidRecordIDException("The start of the enumeration is reached.");
+ }
+ this.lastRecordIndex = previousIndex;
+ int nextRecordId = this.recordIds[previousIndex];
+ return nextRecordId;
+ }
+
+ public void rebuild() {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ reset();
+ this.recordIds = this.sqlDao.getRecordIdsForRecordStore(this.recordStore.getPk());
+ filter();
+ sort();
+ }
+
+ public void reset() {
+ if(isDestroyed()) {
+ throw new IllegalStateException("This RecordEnumeration instance is destroyed.");
+ }
+ this.lastRecordIndex = -1;
+
+ }
+
+ private boolean isDestroyed() {
+ return this.destroyed;
+ }
+
+ private void filter() {
+ if(this.filter == null) {
+ return;
+ }
+ int deleteCount = 0;
+ // Remove recordIds which do not match the filter.
+ // Do this by invalidating not matching ids instead of harvesting the matching ones in a list. This way we safe a lot of object creations when filling the list with Integer objects.
+ int numberOfRecords = this.recordIds.length;
+ for (int currentIndex = 0; currentIndex < numberOfRecords; currentIndex++) {
+ int currentRecordId = this.recordIds[currentIndex];
+ byte[] currentData = this.sqlDao.getRecord(this.recordStore.getPk(),currentRecordId);
+ boolean filterMatches = this.filter.matches(currentData);
+ if( ! filterMatches) {
+ this.recordIds[currentIndex] = -1;
+ deleteCount++;
+ }
+ }
+ if(deleteCount > 0) {
+ int newNumberOfRecords = numberOfRecords-deleteCount;
+ int[] temp = new int[newNumberOfRecords];
+ int tempIndex = 0;
+ for (int currentIndex = 0; currentIndex < numberOfRecords; currentIndex++) {
+ int recordId = this.recordIds[currentIndex];
+ if(recordId != -1) {
+ temp[tempIndex] = recordId;
+ tempIndex++;
+ }
+ }
+ this.recordIds = temp;
+ }
+ }
+
+ private void sort() {
+ if(this.comparator == null) {
+ return;
+ }
+
+ }
+}
Modified: AndroidME/src_MIDP/javax/microedition/rms/RecordStore.java
===================================================================
--- AndroidME/src_MIDP/javax/microedition/rms/RecordStore.java 2010-05-04 13:38:37 UTC (rev 870)
+++ AndroidME/src_MIDP/javax/microedition/rms/RecordStore.java 2010-05-04 15:45:21 UTC (rev 871)
@@ -1,444 +1,416 @@
package javax.microedition.rms;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.EOFException;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
+import net.yura.android.rms.SqlDao;
+import net.yura.android.rms.SqlRecordEnumeration;
-import javax.microedition.midlet.MIDlet;
-import javax.microedition.rms.InvalidRecordIDException;
-import javax.microedition.rms.RecordComparator;
-import javax.microedition.rms.RecordEnumeration;
-import javax.microedition.rms.RecordFilter;
-import javax.microedition.rms.RecordListener;
-import javax.microedition.rms.RecordStore;
-import javax.microedition.rms.RecordStoreException;
-import javax.microedition.rms.RecordStoreFullException;
-import javax.microedition.rms.RecordStoreNotOpenException;
-import net.yura.android.rms.RecordEnumerationImpl;
+public class RecordStore extends Object {
-import android.app.Activity;
-import android.content.Context;
+ public static final int AUTHMODE_PRIVATE = 0;
+ public static final int AUTHMODE_ANY = 1;
-public class RecordStore {
- public static final int AUTHMODE_PRIVATE = 0;
- public static final int AUTHMODE_ANY = 1;
+ private static SqlDao sqlDao;
- private final static String RECORD_STORE_SUFFIX = ".rs";
+ // This mapping contains all open record stores by name. If a record store is not in this mapping, it is not open.
+ private static HashMap<String, RecordStore> openedRecordStores = new HashMap<String, RecordStore>();
- public Hashtable records = new Hashtable();
+ // The unique name of this record store.
+ private String name;
- private String recordStoreName;
- private int version = 0;
- private long lastModified = 0;
- private int nextRecordID = 1;
+ // The version of this object. It changes whenever it is modified.
+ private int version;
- // TODO - Jose
- private static Activity activity = MIDlet.DEFAULT_MIDLET.getActivity();
+ // The id of this record store in the database.
+ private long recordStorePk;
+ // TODO: Use the next to field.
+// private String vendorName;
+// private String suiteName;
+ private int numRecords;
+ private int size;
+ private long sizeAvailable = 4 * 1024 * 1024;
- private transient boolean open;
+ // TODO: Manage lastModified everywhere.
+ private long lastModified;
+ private int nextRecordID = 1;
- private transient Vector recordListeners = new Vector();
+ /**
+ * The number of times this record store was opened. If this number is 0 then this record store is closed.
+ */
+ private int openCount = 0;
+ // TODO: Manage authMode everywhere.
+ private int authMode;
+ // TODO: Manage writable everywhere.
+// private boolean writable = false;
- public RecordStore(String recordStoreName) {
- if (recordStoreName.length() <= 32) {
- this.recordStoreName = recordStoreName;
- } else {
- this.recordStoreName = recordStoreName.substring(0, 32);
- }
- this.open = false;
- }
+ private List<RecordListener> listeners = new ArrayList<RecordListener>();
- public RecordStore(DataInputStream dis) throws IOException {
- this.recordStoreName = dis.readUTF();
- this.version = dis.readInt();
- this.lastModified = dis.readLong();
- this.nextRecordID = dis.readInt();
+ /**
+ * @param name the unique name of this record store within a midlet suite
+ * @param pk the database primary key of this store
+ */
+ public RecordStore(String name, long pk) {
+ this.name = name;
+ this.recordStorePk = pk;
+ }
- try {
- while (true) {
- int recordId = dis.readInt();
- byte[] data = new byte[dis.readInt()];
- dis.read(data, 0, data.length);
- this.records.put(new Integer(recordId), data);
- }
- } catch (EOFException ex) {
- }
- }
- public void write(DataOutputStream dos) throws IOException {
- dos.writeUTF(recordStoreName);
- dos.writeInt(version);
- dos.writeLong(lastModified);
- dos.writeInt(nextRecordID);
+ public static void deleteRecordStore(String recordStoreName) throws RecordStoreException, RecordStoreNotFoundException {
+ RecordStore recordStore = getOpenedRecordStoreFromCache(recordStoreName);
+ if (recordStore != null) {
+ throw new RecordStoreException("The record store '" + recordStoreName + "' is not closed.");
+ }
+ sqlDao.deleteRecordStore(recordStoreName);
- Enumeration en = records.keys();
- while (en.hasMoreElements()) {
- Integer key = (Integer) en.nextElement();
- dos.writeInt(key.intValue());
- byte[] data = (byte[]) records.get(key);
- dos.writeInt(data.length);
- dos.write(data);
- }
- }
+ }
- public boolean isOpen() {
- return open;
- }
- public void setOpen(boolean open) {
- this.open = open;
- }
+ public static RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary) throws RecordStoreException, RecordStoreFullException, RecordStoreNotFoundException {
+ init();
+ if (recordStoreName == null) {
+ throw new IllegalArgumentException("Parameter 'recordStoreName' must not be null or empty.");
+ }
- public void closeRecordStore() throws RecordStoreNotOpenException,
- RecordStoreException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
+ if (recordStoreName.length() < 1 || recordStoreName.length() > 32) {
+ throw new IllegalArgumentException("Parameter 'recordStoreName' must have a length between 1 and 32.");
+ }
- if (recordListeners != null) {
- recordListeners.removeAllElements();
- }
+ // Try the cache.
+ RecordStore recordStore = openRecordStoreFromCache(recordStoreName);
+ if (recordStore != null) {
+ return recordStore;
+ }
- open = false;
- }
+ // Try the datadabase.
+ recordStore = sqlDao.getRecordStore(recordStoreName);
+ if (recordStore != null) {
+ cacheRecordStore(recordStoreName,recordStore);
+ return recordStore;
+ }
+ if (!createIfNecessary) {
+ throw new RecordStoreNotFoundException("No record store with name '" + recordStoreName + "' found.");
+ }
- public String getName() throws RecordStoreNotOpenException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
+ // Create the database.
+ recordStore = sqlDao.createRecordStore(recordStoreName);
+ if (recordStore == null) {
+ throw new RecordStoreException("Could not create record store with name '" + recordStoreName + "'. Reason: The method 'SqlDao.createRecordStore' returned null although it is not allowed to do so.");
+ }
+ cacheRecordStore(recordStoreName, recordStore);
+ return recordStore;
+ }
- return recordStoreName;
- }
- public int getVersion() throws RecordStoreNotOpenException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
+ public static RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary, int authmode, boolean writable) throws RecordStoreException, RecordStoreFullException, RecordStoreNotFoundException {
+ return openRecordStore(recordStoreName, createIfNecessary);
+ }
- synchronized (this) {
- return version;
- }
- }
- public int getNumRecords() throws RecordStoreNotOpenException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
+ public static RecordStore openRecordStore(String recordStoreName, String vendorName, String suiteName) throws RecordStoreException, RecordStoreNotFoundException {
+ return openRecordStore(recordStoreName, true);
+ }
- synchronized (this) {
- return records.size();
- }
- }
- public int getSize() throws RecordStoreNotOpenException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
+ public void setMode(int authmode, boolean writable) throws RecordStoreException {
+ // TODO implement setMode
+ }
- int size = 0;
- for (Enumeration keys = records.keys(); keys.hasMoreElements();) {
- size += ((byte[]) records.get(keys.nextElement())).length;
- }
- return size;
- }
+ public void closeRecordStore() throws RecordStoreNotOpenException, RecordStoreException {
+ if(isClosed()) {
+ return;
+ }
+ boolean closed = closeChachedRecordStore();
- public int getSizeAvailable() throws RecordStoreNotOpenException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
+ // When there are no more open instances of this record store around, inform the listeners.
+ if(closed) {
+ synchronized (this.listeners) {
+ this.listeners.clear();
+ }
+ }
+ }
- try {
- String storeDir = activity.getFilesDir().getPath();
- android.os.StatFs fs = new android.os.StatFs(storeDir);
- long fsSize = fs.getFreeBlocks() * fs.getBlockSize();
- fsSize = (fsSize / 100) * 80;
- fsSize = Math.min(fsSize, Integer.MAX_VALUE);
+ public static String[] listRecordStores() {
+ init();
+ String[] listRecordStores = sqlDao.listRecordStores();
+ if (listRecordStores.length == 0) {
+ return null;
+ }
+ return listRecordStores;
+ }
- return (int) fsSize;
- } catch (Throwable e) {
- }
+ public String getName() throws RecordStoreNotOpenException {
+ return this.name;
+ }
- return 4 * 1024 * 1024;
- }
- public long getLastModified() throws RecordStoreNotOpenException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
+ public int getVersion() throws RecordStoreNotOpenException {
+ return this.version;
+ }
- synchronized (this) {
- return lastModified;
- }
- }
- public void addRecordListener(RecordListener listener) {
- if (!recordListeners.contains(listener)) {
- recordListeners.addElement(listener);
- }
- }
+ public int getNumRecords() throws RecordStoreNotOpenException {
+ return this.numRecords;
+ }
- public void removeRecordListener(RecordListener listener) {
- recordListeners.removeElement(listener);
- }
- public int getNextRecordID() throws RecordStoreNotOpenException,
- RecordStoreException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
+ public int getSize() throws RecordStoreNotOpenException {
+ return this.size;
+ }
- synchronized (this) {
- return nextRecordID;
- }
- }
- public int addRecord(byte[] data, int offset, int numBytes)
- throws RecordStoreNotOpenException, RecordStoreException,
- RecordStoreFullException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
- if (data == null && numBytes > 0) {
- throw new NullPointerException();
- }
- if (numBytes > getSizeAvailable()) {
- throw new RecordStoreFullException();
- }
+ public int getSizeAvailable() throws RecordStoreNotOpenException {
- byte[] recordData = new byte[numBytes];
- if (data != null) {
- System.arraycopy(data, offset, recordData, 0, numBytes);
- }
+ if (this.sizeAvailable > Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ }
+ return (int) this.sizeAvailable;
+ }
- int curRecordID;
- synchronized (this) {
- records.put(new Integer(nextRecordID), recordData);
- version++;
- curRecordID = nextRecordID;
- nextRecordID++;
- lastModified = System.currentTimeMillis();
- }
- saveChanges(this);
+ public long getLastModified() throws RecordStoreNotOpenException {
+ return this.lastModified;
+ }
- return curRecordID;
- }
- public void deleteRecord(int recordId) throws RecordStoreNotOpenException,
- InvalidRecordIDException, RecordStoreException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
+ public void addRecordListener(RecordListener listener) {
+ synchronized (this.listeners) {
+ if (!this.listeners.contains(listener)) {
+ this.listeners.add(listener);
+ }
+ }
+ }
- synchronized (this) {
- if (records.remove(new Integer(recordId)) == null) {
- throw new InvalidRecordIDException();
- }
- version++;
- lastModified = System.currentTimeMillis();
- }
- saveChanges(this);
- }
+ public void removeRecordListener(RecordListener listener) {
+ synchronized (this.listeners) {
+ if (!this.listeners.contains(listener)) {
+ this.listeners.remove(listener);
+ }
+ }
+ }
- public int getRecordSize(int recordId) throws RecordStoreNotOpenException,
- InvalidRecordIDException, RecordStoreException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
- synchronized (this) {
- byte[] data = (byte[]) records.get(new Integer(recordId));
- if (data == null) {
- throw new InvalidRecordIDException();
- }
+ public int getNextRecordID() throws RecordStoreNotOpenException, RecordStoreException {
+ if (isClosed()) {
+ throw new RecordStoreNotOpenException("");
+ }
+ return this.nextRecordID;
+ }
- return data.length;
- }
- }
- public int getRecord(int recordId, byte[] buffer, int offset)
- throws RecordStoreNotOpenException, InvalidRecordIDException,
- RecordStoreException {
- int recordSize;
- synchronized (this) {
- recordSize = getRecordSize(recordId);
- System.arraycopy(records.get(new Integer(recordId)), 0, buffer,
- offset, recordSize);
- }
+ public int addRecord(byte[] data, int offset, int numBytes) throws RecordStoreNotOpenException, RecordStoreException, RecordStoreFullException {
- return recordSize;
- }
+ if (isClosed()) {
+ throw new RecordStoreNotOpenException("The record store is not open because it was closed. This RecordStore object is invalid and will stay so.");
+ }
+ if (data == null) {
+ data = new byte[0];
+ }
+ if (data.length != 0 && offset >= data.length) {
+ throw new RecordStoreException("The offset '" + offset + "' is beyond the size of the data array of '" + data.length + "'");
+ }
+ if (numBytes < 0) {
+ throw new RecordStoreException("The number of bytes '" + numBytes + "' must not be negative.");
+ }
+ if (offset < 0) {
+ throw new RecordStoreException("The offset '" + offset + "' must not be negative.");
+ }
+ if (offset + numBytes > data.length) {
+ throw new RecordStoreException("The Parameter numBytes with value '" + numBytes + "' exceeds the number of available bytes if counted from offset '" + offset + "'");
+ }
+ byte[] actualData = new byte[numBytes];
+ System.arraycopy(data, offset, actualData, 0, numBytes);
+ int recordId = sqlDao.addRecord(getPk(), actualData);
+ // The addRecord method will increment the nextRecordId in the database.
+ // So we update the cache accordingly.
+ RecordStore recordStore = sqlDao.getRecordStore(getPk());
+ updateRecordStoreInstance(recordStore);
+ fireRecordAddedEvent(recordId);
+ return recordId;
+ }
- public byte[] getRecord(int recordId) throws RecordStoreNotOpenException,
- InvalidRecordIDException, RecordStoreException {
- byte[] data;
+ // TODO: What about concurrent updates?
+ private void updateRecordStoreInstance(RecordStore recordStore) throws RecordStoreException {
+ this.name = recordStore.name;
+ this.nextRecordID = recordStore.nextRecordID;
+ this.numRecords = recordStore.numRecords;
+ this.size = recordStore.size;
+ this.version = recordStore.version;
+ this.recordStorePk = recordStore.recordStorePk;
+ this.authMode = recordStore.authMode;
+ }
- synchronized (this) {
- data = new byte[getRecordSize(recordId)];
- getRecord(recordId, data, 0);
- }
- return data.length < 1 ? null : data;
- }
+ public void deleteRecord(int recordId) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException {
+ if (isClosed()) {
+ throw new RecordStoreNotOpenException();
+ }
+ if (recordId < 0) {
+ throw new InvalidRecordIDException();
+ }
+ sqlDao.removeRecord(getPk(), recordId);
+ RecordStore recordStore = sqlDao.getRecordStore(getPk());
+ updateRecordStoreInstance(recordStore);
+ fireRecordDeletedEvent(recordId);
+ }
- public void setRecord(int recordId, byte[] newData, int offset, int numBytes)
- throws RecordStoreNotOpenException, InvalidRecordIDException,
- RecordStoreException, RecordStoreFullException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
- // FIXME fixit
- if (numBytes > getSizeAvailable()) {
- throw new RecordStoreFullException();
- }
+ public int getRecordSize(int recordId) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException {
- byte[] recordData = new byte[numBytes];
- System.arraycopy(newData, offset, recordData, 0, numBytes);
+ byte[] data = getRecord(recordId);
+ return (data == null) ? 0 : data.length;
+ }
- synchronized (this) {
- Integer id = new Integer(recordId);
- if (records.remove(id) == null) {
- throw new InvalidRecordIDException();
- }
- records.put(id, recordData);
- version++;
- lastModified = System.currentTimeMillis();
- }
- saveChanges(this);
- }
+ public int getRecord(int recordId, byte[] buffer, int offset) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException {
+ byte[] data = getRecord(recordId);
- public RecordEnumeration enumerateRecords(RecordFilter filter,
- RecordComparator comparator, boolean keepUpdated)
- throws RecordStoreNotOpenException {
- if (!open) {
- throw new RecordStoreNotOpenException();
- }
+ System.arraycopy(data, 0, buffer, offset, data.length);
- return new RecordEnumerationImpl(this, filter, comparator, keepUpdated);
- }
+ return data.length - offset;
+ }
- // TODO there should be a public constructors
- // private RecordStore() {
- //
- // }
- public static void deleteRecordStore(String recordStoreName)
- throws RecordStoreException, RecordStoreNotFoundException {
- String storeFileName = getSuiteName() + "." + recordStoreName
- + RECORD_STORE_SUFFIX;
- activity.deleteFile(storeFileName);
- }
+ public byte[] getRecord(int recordId) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException {
+ if (isClosed()) {
+ throw new RecordStoreNotOpenException();
+ }
+ if (recordId < 0) {
+ throw new InvalidRecordIDException();
+ }
+ byte[] record = sqlDao.getRecord(getPk(), recordId);
+ return record;
+ }
- public static String[] listRecordStores() {
- String[] result = activity.fileList();
- if (result != null) {
- if (result.length == 0) {
- result = null;
- } else {
- String prefix = getSuiteName() + ".";
- for (int i = 0; i < result.length; i++) {
- int startIdx = (result[i].startsWith(prefix)) ? prefix
- .length() : 0;
- int endIdx = result[i].length()
- - RECORD_STORE_SUFFIX.length();
+ public void setRecord(int recordId, byte[] newData, int offset, int numBytes) throws RecordStoreNotOpenException, InvalidRecordIDException, RecordStoreException, RecordStoreFullException {
+ if (isClosed()) {
+ throw new RecordStoreNotOpenException();
+ }
+ if (recordId < 0) {
+ throw new InvalidRecordIDException("The parameter 'recordId' must not be negative.");
+ }
+ if (newData == null) {
+ newData = new byte[0];
+ }
- result[i] = result[i].substring(startIdx, endIdx);
- }
- }
- }
- return result;
- }
+ byte[] data = new byte[numBytes];
+ System.arraycopy(newData, offset, data, 0, numBytes);
- public static RecordStore openRecordStore(String recordStoreName,
- boolean createIfNecessary) throws RecordStoreException,
- RecordStoreFullException, RecordStoreNotFoundException {
- String storeFileName = getSuiteName() + "." + recordStoreName
- + RECORD_STORE_SUFFIX;
+ sqlDao.setRecord(getPk(), recordId, data);
+ RecordStore recordStore = sqlDao.getRecordStore(getPk());
+ updateRecordStoreInstance(recordStore);
+ fireRecordChangedEvent(recordId);
+ }
- RecordStore recordStore;
- try {
- recordStore = loadFromDisk(storeFileName);
- } catch (FileNotFoundException e) {
- if (!createIfNecessary) {
- throw new RecordStoreNotFoundException(recordStoreName);
- }
- recordStore = new RecordStore(recordStoreName);
- saveToDisk(getSuiteName() + "." + recordStoreName
- + RECORD_STORE_SUFFIX, recordStore);
- }
- recordStore.setOpen(true);
- return recordStore;
- }
+ public RecordEnumeration enumerateRecords(RecordFilter filter, RecordComparator comparator, boolean keepUpdated) throws RecordStoreNotOpenException {
+ SqlRecordEnumeration sqlRecordEnumeration = new SqlRecordEnumeration(this, filter, comparator, keepUpdated);
+ return sqlRecordEnumeration;
+ }
- public static RecordStore openRecordStore(String recordStoreName,
- boolean createIfNecessary, int authmode, boolean writable)
- throws RecordStoreException, RecordStoreFullException,
- RecordStoreNotFoundException {
- // TODO Not yet implemented
- return openRecordStore(recordStoreName, createIfNecessary);
- }
+ private static void init() {
+ if (sqlDao == null) {
+ sqlDao = SqlDao.getInstance();
+ }
+ }
- public static RecordStore openRecordStore(String recordStoreName,
- String vendorName, String suiteName) throws RecordStoreException,
- RecordStoreNotFoundException {
- // TODO Not yet implemented
- return openRecordStore(recordStoreName, false);
- }
- private static void saveToDisk(String recordStoreFileName,
- final RecordStore recordStore) throws RecordStoreException {
- try {
- DataOutputStream dos = new DataOutputStream(activity
- .openFileOutput(recordStoreFileName, Context.MODE_PRIVATE));
- recordStore.write(dos);
- dos.close();
- } catch (IOException e) {
- throw new RecordStoreException(e.getMessage());
- }
- }
+ private void fireRecordAddedEvent(int recordId) {
+ synchronized (this.listeners) {
+ for (Iterator<RecordListener> iterator = this.listeners.iterator(); iterator.hasNext();) {
+ RecordListener recordListener = iterator.next();
+ recordListener.recordAdded(this, recordId);
+ }
+ }
+ }
- private static RecordStore loadFromDisk(String recordStoreFileName)
- throws FileNotFoundException {
- RecordStore store = null;
- try {
- DataInputStream dis = new DataInputStream(activity
- .openFileInput(recordStoreFileName));
- store = new RecordStore(dis);
- dis.close();
- } catch (FileNotFoundException e) {
- throw e;
- } catch (IOException e) {
- e.printStackTrace();
- }
- catch (Throwable e) {
- e.printStackTrace();
- }
- return store;
- }
+ private void fireRecordChangedEvent(int recordId) {
+ synchronized (this.listeners) {
+ for (Iterator<RecordListener> iterator = this.listeners.iterator(); iterator.hasNext();) {
+ RecordListener recordListener = iterator.next();
+ recordListener.recordChanged(this, recordId);
+ }
+ }
+ }
- private static String getSuiteName() {
- return activity.getComponentName().getPackageName();
- }
+ private void fireRecordDeletedEvent(int recordId) {
+ synchronized (this.listeners) {
+ for (Iterator<RecordListener> iterator = this.listeners.iterator(); iterator.hasNext();) {
+ RecordListener recordListener = iterator.next();
+ recordListener.recordDeleted(this, recordId);
+ }
+ }
+ }
- private void saveChanges(RecordStore recordStore)
- throws RecordStoreNotOpenException, RecordStoreException {
- saveToDisk(getSuiteName() + "." + recordStore.getName()
- + RECORD_STORE_SUFFIX, recordStore);
- }
+ // Android Only
+ public synchronized boolean isClosed() {
+ return this.openCount <= 0;
+ }
+
+ // Android Only
+ public long getPk() {
+ return this.recordStorePk;
+ }
+
+ // Android Only
+ public void setVersion(int version) {
+ this.version = version;
+ }
+
+ // Android Only
+ public void setNextId(int nextRecordId) {
+ this.nextRecordID = nextRecordId;
+ }
+
+ // Android Only
+ public void setNumberOfRecords(int numberOfRecords) {
+ this.numRecords = numberOfRecords;
+ }
+
+ // Android Only
+ public void setSize(int size) {
+ this.size = size;
+ }
+
+ private static RecordStore getOpenedRecordStoreFromCache(String recordStoreName) {
+ return openedRecordStores.get(recordStoreName);
+ }
+
+
+ private static void cacheRecordStore(String recordStoreName,RecordStore recordStore) {
+ openedRecordStores.put(recordStoreName, recordStore);
+ recordStore.openCount++;
+ }
+
+ /**
+ * Returns a cached record store and increases the open count.
+ * @param recordStoreName
+ * @return
+ */
+ private static RecordStore openRecordStoreFromCache(String recordStoreName) {
+ RecordStore recordStore = openedRecordStores.get(recordStoreName);
+ if(recordStore != null) {
+ recordStore.openCount++;
+ }
+ return recordStore;
+ }
+
+ private boolean closeChachedRecordStore() {
+ this.openCount--;
+ if (this.openCount > 0) {
+ return false;
+ }
+ openedRecordStores.remove(this.name);
+ return true;
+ }
+
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|