/*
* Copyright © 2016 TIBCO Software,Inc.All rights reserved.
* http://community.jaspersoft.com/project/jaspermobile-android
*
* Unless you have purchased a commercial license agreement from TIBCO Jaspersoft,
* the following license terms apply:
*
* This program is part of TIBCO Jaspersoft Mobile for Android.
*
* TIBCO Jaspersoft Mobile is free software:you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation,either version 3of the License,or
* (at your option)any later version.
*
* TIBCO Jaspersoft Mobile is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY;without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with TIBCO Jaspersoft Mobile for Android.If not,see
* <http://www.gnu.org/licenses/lgpl>.
*/
package com.jaspersoft.android.jaspermobile.db.migrate;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import timber.log.Timber;
/**
* @author Tom Koptel
* @since 2.1
*/
final class MigrationV3 implements Migration {
private final Context mContext;
public MigrationV3(Context context) {
mContext = context;
}
@Override
public void migrate(SQLiteDatabase database) {
migrateProfiles(database);
migrateFavorites(database);
migrateSavedItems(database);
}
private void migrateProfiles(SQLiteDatabase database) {
Timber.d("Start migrating profiles");
new LegacyProfileMigration().migrate(database);
Timber.d("Start migrating accounts");
new ProfilesToAccountsMigration(mContext).migrate(database);
}
void migrateFavorites(SQLiteDatabase database) {
Timber.d("Start migrating favorites");
new FavoriteTableColumnsMigration().migrate(database);
new ProfileFavoritesMigration().migrate(database);
}
private void migrateSavedItems(SQLiteDatabase database) {
Timber.d("Start migrating saved items");
new SavedItemsMigration(mContext).migrate(database);
}
final static class LegacyProfileMigration implements Migration {
private static final String LEGACY_MOBILE_DEMO_ALIAS = "Mobile Demo";
private static final String LEGACY_NAME = "Legacy Mobile Demo";
@Override
public void migrate(SQLiteDatabase database) {
updateLegacyProfile(database);
}
private void updateLegacyProfile(SQLiteDatabase database) {
ContentValues contentValues = new ContentValues();
contentValues.put("alias", LEGACY_NAME);
database.update("server_profiles", contentValues, "alias=?", new String[] {LEGACY_MOBILE_DEMO_ALIAS});
}
}
final static class ProfilesToAccountsMigration implements Migration {
private final static String TABLE_NAME = "server_profiles";
private final static String _ID = "_id";
private final static String ALIAS = "alias";
private final static String SERVER_URL = "server_url";
private final static String ORGANIZATION = "organization";
private final static String USERNAME = "username";
private final static String PASSWORD = "password";
private final static String EDITION = "edition";
private final static String VERSION_CODE = "version_code";
private final static String[] ALL_COLUMNS = new String[]{_ID, ALIAS, SERVER_URL, ORGANIZATION, USERNAME, PASSWORD, EDITION, VERSION_CODE};
private final Context mContext;
private final AccountManager mAccountManager;
ProfilesToAccountsMigration(Context context) {
mContext = context;
mAccountManager = AccountManager.get(mContext);
}
@Override
public void migrate(SQLiteDatabase database) {
adaptProfilesToAccounts(database);
activateAccount(database);
}
private void adaptProfilesToAccounts(SQLiteDatabase db) {
Cursor cursor = db.query(TABLE_NAME, ALL_COLUMNS, null, null, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
do {
adaptProfile(cursor);
} while (cursor.moveToNext());
}
} finally {
cursor.close();
}
}
private void adaptProfile(Cursor cursor) {
String alias = cursor.getString(cursor.getColumnIndex(ALIAS));
String serverUrl = cursor.getString(cursor.getColumnIndex(SERVER_URL));
String organization = cursor.getString(cursor.getColumnIndex(ORGANIZATION));
String username = cursor.getString(cursor.getColumnIndex(USERNAME));
String password = cursor.getString(cursor.getColumnIndex(PASSWORD));
double versionName = cursor.getDouble(cursor.getColumnIndex(VERSION_CODE));
String edition = cursor.getString(cursor.getColumnIndex(EDITION));
edition = TextUtils.isEmpty(edition) ? "?" : edition;
Account account = new Account(alias, "com.jaspersoft");
mAccountManager.addAccountExplicitly(account, password, null);
mAccountManager.setUserData(account, "ALIAS_KEY", alias);
mAccountManager.setUserData(account, "SERVER_URL_KEY", serverUrl);
mAccountManager.setUserData(account, "ORGANIZATION_KEY", organization);
mAccountManager.setUserData(account, "USERNAME_KEY", username);
mAccountManager.setUserData(account, "EDITION_KEY", edition);
mAccountManager.setUserData(account, "VERSION_NAME_KEY", String.valueOf(versionName));
}
private void activateAccount(SQLiteDatabase db) {
SharedPreferences pref = mContext.getSharedPreferences("GeneralPref", 0);
long profileId = pref.getLong("currentProfileId", 0);
Cursor cursor = db.query(TABLE_NAME,
ALL_COLUMNS, _ID + "=" + profileId,
null, null, null, null);
try {
if (cursor.getCount() > 0) {
cursor.moveToFirst();
String alias = cursor.getString(cursor.getColumnIndex(ALIAS));
SharedPreferences preference = mContext.getSharedPreferences("JasperAccountManager", Activity.MODE_PRIVATE);
preference.edit().putString("ACCOUNT_NAME_KEY", alias).apply();
}
} finally {
cursor.close();
}
}
}
static final class FavoriteTableColumnsMigration implements Migration {
@Override
public void migrate(SQLiteDatabase database) {
addAccountNameColumn(database);
addCreationTimeColumn(database);
}
private void addAccountNameColumn(SQLiteDatabase database) {
database.execSQL("ALTER TABLE favorites ADD COLUMN account_name TEXT NOT NULL DEFAULT 'com.jaspersoft.account.none';");
}
private void addCreationTimeColumn(SQLiteDatabase database) {
database.execSQL("ALTER TABLE favorites ADD COLUMN creation_time TEXT DEFAULT '';");
}
}
final static class ProfileFavoritesMigration implements Migration {
@Override
public void migrate(SQLiteDatabase database) {
populateAccountNameColumn(database);
removeServerProfileIdColumn(database);
}
private void populateAccountNameColumn(SQLiteDatabase database) {
Cursor profilesCursor = database.rawQuery("SELECT _id, alias FROM server_profiles", null);
try {
if (profilesCursor != null && profilesCursor.getCount() > 0) {
addAccountNameIntoFavoritesForProfile(profilesCursor, database);
}
} finally {
if (profilesCursor != null) profilesCursor.close();
}
}
private void addAccountNameIntoFavoritesForProfile(Cursor profilesCursor, SQLiteDatabase database) {
ContentValues contentValues = new ContentValues();
String id, alias;
while (profilesCursor.moveToNext()) {
id = profilesCursor.getString(profilesCursor.getColumnIndex("_id"));
alias = profilesCursor.getString(profilesCursor.getColumnIndex("alias"));
contentValues.clear();
contentValues.put("account_name", alias);
database.update("favorites", contentValues, "server_profile_id=?", new String[]{id});
}
}
private void removeServerProfileIdColumn(SQLiteDatabase database) {
database.execSQL("ALTER TABLE favorites RENAME TO tmp_favorites;");
database.execSQL(
"CREATE TABLE favorites ( _id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, uri TEXT, " +
"description TEXT, wstype TEXT, username TEXT, organization TEXT, account_name TEXT NOT NULL DEFAULT 'com.jaspersoft.account.none', creation_time TEXT )"
);
database.execSQL("INSERT INTO favorites(title, uri, description, wstype, username, organization, account_name, creation_time)" +
" select title, uri, description, wstype, username, organization, account_name, creation_time from tmp_favorites;");
database.execSQL("DROP TABLE IF EXISTS tmp_favorites;");
}
}
final static class SavedItemsMigration implements Migration {
private static final String SAVED_REPORTS_DIR_NAME = "saved.reports";
private static final String SHARED_DIR = "com.jaspersoft.account.none";
private static final String TAG = SavedItemsMigration.class.getSimpleName();
private final Context mContext;
public SavedItemsMigration(Context context) {
mContext = context;
Timber.tag(TAG);
}
@Override
public void migrate(SQLiteDatabase database) {
database.execSQL(
"CREATE TABLE saved_items ( _id INTEGER PRIMARY KEY AUTOINCREMENT," +
" file_path TEXT NOT NULL, name TEXT NOT NULL," +
" file_format TEXT NOT NULL, description TEXT, " +
"wstype TEXT NOT NULL DEFAULT 'unknown'," +
" account_name TEXT NOT NULL DEFAULT 'com.jaspersoft.account.none'," +
" creation_time NUMERIC NOT NULL )"
);
migrateSavedItems(database);
}
private void migrateSavedItems(SQLiteDatabase db) {
File savedItemsDir = getSavedItemsDir();
if (savedItemsDir != null) {
File[] savedItems = savedItemsDir.listFiles();
File sharedDir = createShareDirectory(savedItemsDir);
if (sharedDir != null) {
if (savedItems.length > 0) {
moveToSharedDir(savedItems, sharedDir);
saveSharedFilesInDb(db, sharedDir);
}
}
}
}
@Nullable
private File createShareDirectory(File savedItemsDir) {
File sharedDir = new File(savedItemsDir, SHARED_DIR);
if (!sharedDir.exists() && !sharedDir.mkdir()) return null;
return sharedDir;
}
@Nullable
private File getSavedItemsDir() {
File appFilesDir = mContext.getExternalFilesDir(null);
File savedReportsDir = new File(appFilesDir, SAVED_REPORTS_DIR_NAME);
if (!savedReportsDir.exists()) {
boolean created = savedReportsDir.mkdir();
if (!created) {
Timber.w("Unable to create %s", savedReportsDir);
return null;
}
}
return savedReportsDir;
}
private void moveToSharedDir(File[] savedItems, File sharedDir) {
for (File savedItem : savedItems) {
try {
FileUtils.moveDirectoryToDirectory(savedItem, sharedDir, false);
} catch (IOException e) {
Timber.w(e, "Failed to move file to shared destination");
}
}
}
private void saveSharedFilesInDb(SQLiteDatabase db, File sharedDir) {
ContentValues contentValues = new ContentValues();
File[] savedItems = sharedDir.listFiles();
String fileName, fileFormat;
long creationTime;
File savedReport;
for (File savedItem : savedItems) {
savedReport = new File(savedItem, savedItem.getName());
fileName = FilenameUtils.getBaseName(savedItem.getName());
fileFormat = FilenameUtils.getExtension(savedItem.getName()).toUpperCase(Locale.getDefault());
creationTime = savedItem.lastModified();
contentValues.clear();
contentValues.put("file_path", savedReport.getPath());
contentValues.put("name", fileName);
contentValues.put("file_format", fileFormat);
contentValues.put("creation_time", creationTime);
contentValues.put("account_name", "com.jaspersoft.account.none");
db.insert("saved_items", null, contentValues);
}
}
}
}