2015-05-30 17:28:03 +02:00
package nodomain.freeyourgadget.gadgetbridge.database ;
import android.content.ContentValues ;
import android.content.Context ;
import android.database.Cursor ;
import android.database.sqlite.SQLiteDatabase ;
import android.database.sqlite.SQLiteOpenHelper ;
2015-07-10 00:31:45 +02:00
import android.widget.Toast ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
2015-05-30 17:28:03 +02:00
import java.util.ArrayList ;
2015-08-03 23:09:49 +02:00
import nodomain.freeyourgadget.gadgetbridge.util.GB ;
import nodomain.freeyourgadget.gadgetbridge.impl.GBActivitySample ;
2015-08-03 01:17:02 +02:00
import nodomain.freeyourgadget.gadgetbridge.GBApplication ;
2015-08-03 23:09:49 +02:00
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind ;
2015-07-10 00:31:45 +02:00
import nodomain.freeyourgadget.gadgetbridge.database.schema.ActivityDBCreationScript ;
2015-07-27 23:49:53 +02:00
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample ;
2015-08-03 23:09:49 +02:00
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider ;
2015-05-30 17:28:03 +02:00
2015-07-13 21:54:46 +02:00
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.DATABASE_NAME ;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_INTENSITY ;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_PROVIDER ;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_STEPS ;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TIMESTAMP ;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TYPE ;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_GBACTIVITYSAMPLES ;
2015-05-30 17:28:03 +02:00
2015-08-03 01:17:02 +02:00
public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandler {
2015-05-30 17:28:03 +02:00
2015-07-10 00:31:45 +02:00
private static final Logger LOG = LoggerFactory . getLogger ( ActivityDatabaseHandler . class ) ;
2015-05-30 17:28:03 +02:00
2015-07-10 00:31:45 +02:00
private static final int DATABASE_VERSION = 5 ;
2015-05-30 17:28:03 +02:00
public ActivityDatabaseHandler ( Context context ) {
super ( context , DATABASE_NAME , null , DATABASE_VERSION ) ;
}
@Override
public void onCreate ( SQLiteDatabase db ) {
2015-07-10 00:31:45 +02:00
try {
ActivityDBCreationScript script = new ActivityDBCreationScript ( ) ;
script . createSchema ( db ) ;
} catch ( RuntimeException ex ) {
2015-07-11 21:49:51 +02:00
GB . toast ( " Error creating database. " , Toast . LENGTH_SHORT , GB . ERROR , ex ) ;
2015-07-10 00:31:45 +02:00
}
2015-05-30 17:28:03 +02:00
}
2015-07-10 00:31:45 +02:00
@Override
public void onUpgrade ( SQLiteDatabase db , int oldVersion , int newVersion ) {
try {
for ( int i = oldVersion + 1 ; i < = newVersion ; i + + ) {
DBUpdateScript updater = getUpdateScript ( db , i ) ;
if ( updater ! = null ) {
LOG . info ( " upgrading activity database to version " + i ) ;
updater . upgradeSchema ( db ) ;
}
}
LOG . info ( " activity database is now at version " + newVersion ) ;
} catch ( RuntimeException ex ) {
2015-07-11 21:49:51 +02:00
GB . toast ( " Error upgrading database. " , Toast . LENGTH_SHORT , GB . ERROR , ex ) ;
2015-07-10 00:31:45 +02:00
throw ex ; // reject upgrade
2015-06-06 00:10:38 +02:00
}
}
2015-05-30 17:28:03 +02:00
@Override
2015-07-10 00:31:45 +02:00
public void onDowngrade ( SQLiteDatabase db , int oldVersion , int newVersion ) {
try {
for ( int i = oldVersion ; i > = newVersion ; i - - ) {
DBUpdateScript updater = getUpdateScript ( db , i ) ;
if ( updater ! = null ) {
LOG . info ( " downgrading activity database to version " + ( i - 1 ) ) ;
updater . downgradeSchema ( db ) ;
}
}
LOG . info ( " activity database is now at version " + newVersion ) ;
} catch ( RuntimeException ex ) {
2015-07-11 21:49:51 +02:00
GB . toast ( " Error downgrading database. " , Toast . LENGTH_SHORT , GB . ERROR , ex ) ;
2015-07-10 00:31:45 +02:00
throw ex ; // reject downgrade
2015-06-04 21:37:48 +02:00
}
2015-05-30 17:28:03 +02:00
}
2015-07-10 00:31:45 +02:00
private DBUpdateScript getUpdateScript ( SQLiteDatabase db , int version ) {
try {
Class < ? > updateClass = getClass ( ) . getClassLoader ( ) . loadClass ( getClass ( ) . getPackage ( ) . getName ( ) + " .schema.ActivityDBUpdate_ " + version ) ;
return ( DBUpdateScript ) updateClass . newInstance ( ) ;
} catch ( ClassNotFoundException e ) {
return null ;
} catch ( InstantiationException | IllegalAccessException e ) {
throw new RuntimeException ( " Error instantiating DBUpdate class for version " + version , e ) ;
}
}
2015-05-30 17:28:03 +02:00
2015-07-27 23:49:53 +02:00
public void addGBActivitySample ( ActivitySample sample ) {
2015-06-04 23:45:46 +02:00
try ( SQLiteDatabase db = this . getWritableDatabase ( ) ) {
ContentValues values = new ContentValues ( ) ;
2015-07-27 23:49:53 +02:00
values . put ( KEY_TIMESTAMP , sample . getTimestamp ( ) ) ;
values . put ( KEY_PROVIDER , sample . getProvider ( ) . getID ( ) ) ;
values . put ( KEY_INTENSITY , sample . getRawIntensity ( ) ) ;
values . put ( KEY_STEPS , sample . getSteps ( ) ) ;
values . put ( KEY_TYPE , sample . getRawKind ( ) ) ;
2015-06-04 23:45:46 +02:00
db . insert ( TABLE_GBACTIVITYSAMPLES , null , values ) ;
}
2015-05-30 17:28:03 +02:00
}
2015-07-27 23:49:53 +02:00
/ * *
* Adds the a new sample to the database
2015-07-28 17:30:20 +02:00
*
2015-07-27 23:49:53 +02:00
* @param timestamp the timestamp of the same , second - based !
2015-07-28 17:30:20 +02:00
* @param provider the SampleProvider ID
2015-07-27 23:49:53 +02:00
* @param intensity the sample ' s raw intensity value
2015-07-28 17:30:20 +02:00
* @param steps the sample ' s steps value
* @param kind the raw activity kind of the sample
2015-07-27 23:49:53 +02:00
* /
2015-08-15 00:23:13 +02:00
@Override
public void addGBActivitySample ( int timestamp , byte provider , short intensity , short steps , byte kind ) {
2015-06-04 23:45:46 +02:00
try ( SQLiteDatabase db = this . getWritableDatabase ( ) ) {
ContentValues values = new ContentValues ( ) ;
values . put ( KEY_TIMESTAMP , timestamp ) ;
values . put ( KEY_PROVIDER , provider ) ;
values . put ( KEY_INTENSITY , intensity ) ;
values . put ( KEY_STEPS , steps ) ;
2015-07-27 23:49:53 +02:00
values . put ( KEY_TYPE , kind ) ;
2015-06-04 23:45:46 +02:00
db . insert ( TABLE_GBACTIVITYSAMPLES , null , values ) ;
}
2015-05-30 17:28:03 +02:00
}
2015-07-27 23:49:53 +02:00
public ArrayList < ActivitySample > getSleepSamples ( int timestamp_from , int timestamp_to , SampleProvider provider ) {
2015-07-14 00:29:32 +02:00
return getGBActivitySamples ( timestamp_from , timestamp_to , ActivityKind . TYPE_SLEEP , provider ) ;
2015-07-12 23:42:23 +02:00
}
2015-07-27 23:49:53 +02:00
public ArrayList < ActivitySample > getActivitySamples ( int timestamp_from , int timestamp_to , SampleProvider provider ) {
2015-07-14 00:29:32 +02:00
return getGBActivitySamples ( timestamp_from , timestamp_to , ActivityKind . TYPE_ACTIVITY , provider ) ;
2015-07-12 23:42:23 +02:00
}
2015-08-03 01:17:02 +02:00
@Override
public SQLiteOpenHelper getHelper ( ) {
return this ;
}
@Override
public void release ( ) {
GBApplication . releaseDB ( ) ;
}
2015-07-27 23:49:53 +02:00
public ArrayList < ActivitySample > getAllActivitySamples ( int timestamp_from , int timestamp_to , SampleProvider provider ) {
2015-07-14 00:29:32 +02:00
return getGBActivitySamples ( timestamp_from , timestamp_to , ActivityKind . TYPE_ALL , provider ) ;
2015-07-12 23:42:23 +02:00
}
/ * *
* Returns all available activity samples from between the two timestamps ( inclusive ) , of the given
* provided and type ( s ) .
2015-07-25 21:52:52 +02:00
*
2015-07-12 23:42:23 +02:00
* @param timestamp_from
* @param timestamp_to
2015-07-25 21:52:52 +02:00
* @param activityTypes ORed combination of # TYPE_DEEP_SLEEP , # TYPE_LIGHT_SLEEP , # TYPE_ACTIVITY
2015-07-28 17:30:20 +02:00
* @param provider the producer of the samples to be sought
2015-07-12 23:42:23 +02:00
* @return
* /
2015-07-27 23:49:53 +02:00
private ArrayList < ActivitySample > getGBActivitySamples ( int timestamp_from , int timestamp_to , int activityTypes , SampleProvider provider ) {
2015-05-30 17:28:03 +02:00
if ( timestamp_to = = - 1 ) {
2015-06-04 23:45:46 +02:00
timestamp_to = Integer . MAX_VALUE ; // dont know what happens when I use more than max of a signed int
2015-05-30 17:28:03 +02:00
}
2015-07-27 23:49:53 +02:00
ArrayList < ActivitySample > samples = new ArrayList < ActivitySample > ( ) ;
final String where = " (provider= " + provider . getID ( ) + " and timestamp>= " + timestamp_from + " and timestamp<= " + timestamp_to + getWhereClauseFor ( activityTypes , provider ) + " ) " ;
2015-07-12 21:50:09 +02:00
final String order = " timestamp " ;
2015-07-11 00:03:41 +02:00
try ( SQLiteDatabase db = this . getReadableDatabase ( ) ) {
2015-08-16 00:17:16 +02:00
try ( Cursor cursor = db . query ( TABLE_GBACTIVITYSAMPLES , null , where , null , null , null , order ) ) {
if ( cursor . moveToFirst ( ) ) {
do {
GBActivitySample sample = new GBActivitySample (
provider ,
cursor . getInt ( cursor . getColumnIndex ( KEY_TIMESTAMP ) ) ,
cursor . getShort ( cursor . getColumnIndex ( KEY_INTENSITY ) ) ,
cursor . getShort ( cursor . getColumnIndex ( KEY_STEPS ) ) ,
( byte ) cursor . getShort ( cursor . getColumnIndex ( KEY_TYPE ) ) ) ;
samples . add ( sample ) ;
} while ( cursor . moveToNext ( ) ) ;
}
2015-06-04 23:45:46 +02:00
}
2015-05-30 17:28:03 +02:00
}
2015-07-27 23:49:53 +02:00
return samples ;
2015-05-30 17:28:03 +02:00
}
2015-07-13 21:54:46 +02:00
2015-07-27 23:49:53 +02:00
private String getWhereClauseFor ( int activityTypes , SampleProvider provider ) {
2015-07-14 00:29:32 +02:00
if ( activityTypes = = ActivityKind . TYPE_ALL ) {
2015-07-13 21:54:46 +02:00
return " " ; // no further restriction
}
StringBuilder builder = new StringBuilder ( " and ( " ) ;
2015-07-27 23:49:53 +02:00
byte [ ] dbActivityTypes = ActivityKind . mapToDBActivityTypes ( activityTypes , provider ) ;
2015-07-13 21:54:46 +02:00
for ( int i = 0 ; i < dbActivityTypes . length ; i + + ) {
builder . append ( " type= " ) . append ( dbActivityTypes [ i ] ) ;
if ( i + 1 < dbActivityTypes . length ) {
builder . append ( " or " ) ;
}
}
builder . append ( ')' ) ;
return builder . toString ( ) ;
}
2015-06-12 21:26:11 +02:00
}