Android Open Source - force_analytics_example D B Helper






From Project

Back to project page force_analytics_example.

License

The source code is released under:

Copyright (c) 2011, salesforce.com, inc. All rights reserved. ======================================== Redistribution and use of this software in source and binary forms, with or without modificatio...

If you think the Android project force_analytics_example listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (c) 2012, salesforce.com, inc.
 * All rights reserved./*from w  w  w.  jav  a2  s.  co m*/
 * Redistribution and use of this software in source and binary forms, with or
 * without modification, are permitted provided that the following conditions
 * are met:
 * - Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * - Neither the name of salesforce.com, inc. nor the names of its contributors
 * may be used to endorse or promote products derived from this software without
 * specific prior written permission of salesforce.com, inc.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package com.salesforce.androidsdk.smartstore.store;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import net.sqlcipher.DatabaseUtils.InsertHelper;
import net.sqlcipher.database.SQLiteDatabase;
import net.sqlcipher.database.SQLiteDoneException;
import net.sqlcipher.database.SQLiteStatement;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;

import com.salesforce.androidsdk.accounts.UserAccount;
import com.salesforce.androidsdk.smartstore.app.SalesforceSDKManagerWithSmartStore;
import com.salesforce.androidsdk.smartstore.store.SmartStore.SmartStoreException;
import com.salesforce.androidsdk.smartstore.store.SmartStore.Type;

/**
 * SmartStore Database Helper
 * 
 * Singleton class that provides helpful methods for accessing the database underneath the SmartStore
 * It also caches a number of of things to speed things up (e.g. soup table name, index specs, insert helpers etc)
 */
public enum DBHelper  {
  
  INSTANCE;

  // Some queries
  private static final String COUNT_SELECT = "SELECT count(*) FROM %s %s";
  private static final String SEQ_SELECT = "SELECT seq FROM SQLITE_SEQUENCE WHERE name = ?";
  private static final String LIMIT_SELECT = "SELECT * FROM (%s) LIMIT %s";
  
  // Cache of soup name to soup table names
  private Map<String, String> soupNameToTableNamesMap = new HashMap<String, String>();
  
  // Cache of soup name to index specs
  private Map<String, IndexSpec[]> soupNameToIndexSpecsMap = new HashMap<String, IndexSpec[]>();
  
  // Cache of table name to get-next-id compiled statements
  private Map<String, SQLiteStatement> tableNameToNextIdStatementsMap = new HashMap<String, SQLiteStatement>();
  
  // Cache of table name to insert helpers
  private Map<String, InsertHelper> tableNameToInsertHelpersMap = new HashMap<String, InsertHelper>();
  
  // Cache of raw count sql to compiled statements
  private Map<String, SQLiteStatement> rawCountSqlToStatementsMap = new HashMap<String, SQLiteStatement>();
  
  
  /**
   * @param soupName
   * @param tableName
   */
  public void cacheTableName(String soupName, String tableName) {
    soupNameToTableNamesMap.put(soupName, tableName);
  }
  
  /**
   * @param soupName
   * @return
   */
  public String getCachedTableName(String soupName) {
    return soupNameToTableNamesMap.get(soupName);
  }
  
  /**
   * @param soupName
   * @param tableName
   */
  public void cacheIndexSpecs(String soupName, IndexSpec[] indexSpecs) {
    soupNameToIndexSpecsMap.put(soupName, indexSpecs.clone());
  }

  /**
   * @param soupName
   * @return
   */
  public IndexSpec[] getCachedIndexSpecs(String soupName) {
    return soupNameToIndexSpecsMap.get(soupName);
  }
  
  /**
   * @param soupName
   */
  public void removeFromCache(String soupName) {
    String tableName = soupNameToTableNamesMap.get(soupName);
    if (tableName != null) {
      InsertHelper ih = tableNameToInsertHelpersMap.remove(tableName);
      if (ih != null) 
        ih.close();
      
      SQLiteStatement prog = tableNameToNextIdStatementsMap.remove(tableName);
      if (prog != null) 
        prog.close();
      
      cleanupRawCountSqlToStatementMaps(tableName);
    }
    soupNameToTableNamesMap.remove(soupName);
    soupNameToIndexSpecsMap.remove(soupName);
  }

  private void cleanupRawCountSqlToStatementMaps(String tableName) {
    List<String> countSqlToRemove = new ArrayList<String>();
    for (Entry<String, SQLiteStatement>  entry : rawCountSqlToStatementsMap.entrySet()) {
      String countSql = entry.getKey();
      if (countSql.contains(tableName)) {
        SQLiteStatement countProg = entry.getValue();
        if (countProg != null)
          countProg.close();
        countSqlToRemove.add(countSql);
      }
    }
    for (String countSql : countSqlToRemove) {
      rawCountSqlToStatementsMap.remove(countSql);
    }
  }
  
  /**
   * Get next id for a table
   * 
   * @param db
   * @param tableName
   * @return long
   */
  public long getNextId(SQLiteDatabase db, String tableName) {
    SQLiteStatement prog = tableNameToNextIdStatementsMap.get(tableName);
    if (prog == null) {
      prog = db.compileStatement(SEQ_SELECT);
      prog.bindString(1, tableName);
      tableNameToNextIdStatementsMap.put(tableName, prog);
    }
    
    try {
      return prog.simpleQueryForLong() + 1;
    } catch (SQLiteDoneException e) {
      // first time, we don't find any row for the table in the sequence table
      return 1L;
    }
  }

  /**
   * Get insert helper for a table
   * @param table
   * @return
   */
  public InsertHelper getInsertHelper(SQLiteDatabase db, String table) {
    InsertHelper insertHelper = tableNameToInsertHelpersMap.get(table);

    if (insertHelper == null) {
      insertHelper = new InsertHelper(db, table);
      tableNameToInsertHelpersMap.put(table, insertHelper);
    }
    return insertHelper;
  }

  /**
   * Does a count query
   * @param db
   * @param table
   * @param whereClause
   * @param whereArgs
   * @return
   */
  public Cursor countQuery(SQLiteDatabase db, String table, String whereClause, String... whereArgs) {
    String selectionStr = (whereClause == null ? "" : " WHERE " + whereClause);
    String sql = String.format(COUNT_SELECT, table, selectionStr);
    return db.rawQuery(sql, whereArgs);
  }
  
  /**
   * Does a limit for a raw query
   * @param db
   * @param sql
   * @param limit
   * @param whereArgs
   * @return
   */
  public Cursor limitRawQuery(SQLiteDatabase db, String sql, String limit, String... whereArgs) {
    String limitSql = String.format(LIMIT_SELECT, sql, limit);
    return db.rawQuery(limitSql, whereArgs);
  }

  /**
   * Does a count for a raw count query
   * @param db
   * @param sql
   * @param whereArgs
   * @return
   */
  public int countRawCountQuery(SQLiteDatabase db, String countSql, String... whereArgs) {
    SQLiteStatement prog = rawCountSqlToStatementsMap.get(countSql);
    if (prog == null) {
      prog = db.compileStatement(countSql);
      rawCountSqlToStatementsMap.put(countSql, prog);
    }
    
    
    if (whereArgs != null) {
      for (int i=0; i<whereArgs.length; i++) {
        prog.bindString(i+1, whereArgs[i]);
      }
    }
    
    try {
      int count =  (int) prog.simpleQueryForLong();
      prog.clearBindings();
      return count;
    } catch (SQLiteDoneException e) {
      return -1;
    }
  }
  
  /**
   * Does a count for a raw query
   * @param db
   * @param sql
   * @param whereArgs
   * @return
   */
  public int countRawQuery(SQLiteDatabase db, String sql, String... whereArgs) {
    String countSql = String.format(COUNT_SELECT, "", "(" + sql + ")");
    return countRawCountQuery(db, countSql, whereArgs);
  }
  
  /**
   * Runs a query
   * @param db
   * @param table
   * @param columns
   * @param orderBy
   * @param limit
   * @param whereClause
   * @param whereArgs
   * @return
   */
  public Cursor query(SQLiteDatabase db, String table, String[] columns, String orderBy, String limit, String whereClause, String... whereArgs) {
    return db.query(table, columns, whereClause, whereArgs, null, null, orderBy, limit);
  }

  /**
   * Does an insert
   * @param db
   * @param table
   * @param contentValues
   * @return row id of inserted row
   */
  public long insert(SQLiteDatabase db, String table, ContentValues contentValues) {
    InsertHelper ih = getInsertHelper(db, table);
    return ih.insert(contentValues);
  }

  /**
   * Does an update
   * @param db
   * @param table
   * @param contentValues
   * @param whereClause
   * @param whereArgs
   * @return number of rows affected
   */
  public int update(SQLiteDatabase db, String table, ContentValues contentValues, String whereClause, String... whereArgs) {
    return db.update(table, contentValues, whereClause, whereArgs);
  }
  
  /**
   * Does a delete (after first logging the delete statement)
   * @param db
   * @param table
   * @param whereClause
   * @param whereArgs
   */
  public void delete(SQLiteDatabase db, String table, String whereClause, String... whereArgs) {
    db.delete(table, whereClause, whereArgs);
  }

  /**
   * Resets all cached data and deletes the database for all users.
   *
   * @param ctx Context.
   */
  public synchronized void reset(Context ctx) {
    clearMemoryCache();
    final List<UserAccount> accounts = SalesforceSDKManagerWithSmartStore.getInstance().getUserAccountManager().getAuthenticatedUsers();
    if (accounts != null) {
      for (final UserAccount account : accounts) {
        reset(ctx, account);
      }
    }
  }

  /**
   * Resets all cached data and deletes the database for the specified user.
   *
   * @param ctx Context.
   * @param account User account.
   */
  public synchronized void reset(Context ctx, UserAccount account) {
    clearMemoryCache();
    DBOpenHelper.deleteDatabase(ctx, account);
  }

  /**
   * Resets all cached data from memory.
   */
  public synchronized void clearMemoryCache() {

    // Closes all statements.
    for (final InsertHelper  ih : tableNameToInsertHelpersMap.values()) {
      ih.close();
    }
    for (final SQLiteStatement prog : tableNameToNextIdStatementsMap.values()) {
      prog.close();
    }
    for (final SQLiteStatement rawCountSql : rawCountSqlToStatementsMap.values()) {
      rawCountSql.close();
    }

    // Clears all maps.
    soupNameToTableNamesMap.clear();
    soupNameToIndexSpecsMap.clear();
    tableNameToInsertHelpersMap.clear();
    tableNameToNextIdStatementsMap.clear();
    rawCountSqlToStatementsMap.clear();
  }

    /**
     * Return column name in soup table that holds the soup projection for path
     * @param soupName
     * @param path
     * @return
     */
    public String getColumnNameForPath(SQLiteDatabase db, String soupName, String path) {
        IndexSpec[] indexSpecs = getIndexSpecs(db, soupName);
        for (IndexSpec indexSpec : indexSpecs) {
            if (indexSpec.path.equals(path)) {
                return indexSpec.columnName;
            }
        }
        throw new SmartStoreException(String.format("%s does not have an index on %s", soupName, path));
    }  
  
    /**
     * Read index specs back from the soup index map table
     * @param db
     * @param soupName
     * @return
     */
    public IndexSpec[] getIndexSpecs(SQLiteDatabase db, String soupName) {
        IndexSpec[] indexSpecs = getCachedIndexSpecs(soupName);
        if (indexSpecs == null) {
            indexSpecs = getIndexSpecsFromDb(db, soupName);
            cacheIndexSpecs(soupName, indexSpecs);
        }

        return indexSpecs;
    }

    protected IndexSpec[] getIndexSpecsFromDb(SQLiteDatabase db, String soupName) {
        Cursor cursor = null;
        try {
            cursor = query(db, SmartStore.SOUP_INDEX_MAP_TABLE, new String[] {SmartStore.PATH_COL, SmartStore.COLUMN_NAME_COL, SmartStore.COLUMN_TYPE_COL}, null,
                    null, SmartStore.SOUP_NAME_PREDICATE, soupName);

            if (!cursor.moveToFirst()) {
                throw new SmartStoreException(String.format("%s does not have any indices", soupName));
            }

            List<IndexSpec> indexSpecs = new ArrayList<IndexSpec>();
            do {
                String path = cursor.getString(cursor.getColumnIndex(SmartStore.PATH_COL));
                String columnName = cursor.getString(cursor.getColumnIndex(SmartStore.COLUMN_NAME_COL));
                Type columnType = Type.valueOf(cursor.getString(cursor.getColumnIndex(SmartStore.COLUMN_TYPE_COL)));
                indexSpecs.add(new IndexSpec(path, columnType, columnName));
            }
            while (cursor.moveToNext());

            return indexSpecs.toArray(new IndexSpec[0]);
        }
        finally {
            safeClose(cursor);
        }
    }
    
    /**
     * Return table name for a given soup or null if the soup doesn't exist
     * @param db
     * @param soupName
     * @return 
    */
   public String getSoupTableName(SQLiteDatabase db, String soupName) {
       String soupTableName = getCachedTableName(soupName);
       if (soupTableName == null) {
           soupTableName = getSoupTableNameFromDb(db, soupName);
           if (soupTableName != null) {
               cacheTableName(soupName, soupTableName);
           }
           // Note: if you ask twice about a non-existing soup, we go to the database both times
           //       we could optimize for that scenario but it doesn't seem very important
       }

       return soupTableName;
   }

   protected String getSoupTableNameFromDb(SQLiteDatabase db, String soupName) {
       Cursor cursor = null;
       try {
           cursor = query(db, SmartStore.SOUP_NAMES_TABLE, new String[] {SmartStore.ID_COL}, null, null, SmartStore.SOUP_NAME_PREDICATE, soupName);
           if (!cursor.moveToFirst()) {
               return null;
           }
           return SmartStore.getSoupTableName(cursor.getLong(cursor.getColumnIndex(SmartStore.ID_COL)));
       }
       finally {
           safeClose(cursor);
       }
   }
    
    
    /**
     * @param cursor
     */
    protected void safeClose(Cursor cursor) {
        if (cursor != null) {
            cursor.close();
        }
    }
}




Java Source Code List

com.salesforce.androidsdk.accounts.UserAccountManagerWithSmartStore.java
com.salesforce.androidsdk.accounts.UserAccountManager.java
com.salesforce.androidsdk.accounts.UserAccount.java
com.salesforce.androidsdk.app.SalesforceSDKManager.java
com.salesforce.androidsdk.app.UUIDManager.java
com.salesforce.androidsdk.app.UpgradeManager.java
com.salesforce.androidsdk.auth.AccountWatcher.java
com.salesforce.androidsdk.auth.AuthenticatorService.java
com.salesforce.androidsdk.auth.HttpAccess.java
com.salesforce.androidsdk.auth.LoginServerManager.java
com.salesforce.androidsdk.auth.OAuth2.java
com.salesforce.androidsdk.phonegap.ForcePlugin.java
com.salesforce.androidsdk.phonegap.JavaScriptPluginVersion.java
com.salesforce.androidsdk.phonegap.SDKInfoPlugin.java
com.salesforce.androidsdk.phonegap.SFAccountManagerPlugin.java
com.salesforce.androidsdk.phonegap.SalesforceOAuthPlugin.java
com.salesforce.androidsdk.phonegap.TestRunnerPlugin.java
com.salesforce.androidsdk.push.PushBroadcastReceiver.java
com.salesforce.androidsdk.push.PushMessaging.java
com.salesforce.androidsdk.push.PushNotificationInterface.java
com.salesforce.androidsdk.push.PushService.java
com.salesforce.androidsdk.rest.AdminPrefsManager.java
com.salesforce.androidsdk.rest.ApiVersionStrings.java
com.salesforce.androidsdk.rest.BootConfig.java
com.salesforce.androidsdk.rest.ClientManager.java
com.salesforce.androidsdk.rest.RestClient.java
com.salesforce.androidsdk.rest.RestRequest.java
com.salesforce.androidsdk.rest.RestResponse.java
com.salesforce.androidsdk.rest.files.ApiRequests.java
com.salesforce.androidsdk.rest.files.ConnectUriBuilder.java
com.salesforce.androidsdk.rest.files.FileRequests.java
com.salesforce.androidsdk.rest.files.RenditionType.java
com.salesforce.androidsdk.security.Encryptor.java
com.salesforce.androidsdk.security.PRNGFixes.java
com.salesforce.androidsdk.security.PasscodeManager.java
com.salesforce.androidsdk.smartstore.app.SalesforceSDKManagerWithSmartStore.java
com.salesforce.androidsdk.smartstore.app.UpgradeManagerWithSmartStore.java
com.salesforce.androidsdk.smartstore.phonegap.SmartStorePlugin.java
com.salesforce.androidsdk.smartstore.phonegap.StoreCursor.java
com.salesforce.androidsdk.smartstore.store.DBHelper.java
com.salesforce.androidsdk.smartstore.store.DBOpenHelper.java
com.salesforce.androidsdk.smartstore.store.IndexSpec.java
com.salesforce.androidsdk.smartstore.store.QuerySpec.java
com.salesforce.androidsdk.smartstore.store.SmartSqlHelper.java
com.salesforce.androidsdk.smartstore.store.SmartStore.java
com.salesforce.androidsdk.ui.AccountSwitcherActivity.java
com.salesforce.androidsdk.ui.CustomServerUrlEditor.java
com.salesforce.androidsdk.ui.LoginActivity.java
com.salesforce.androidsdk.ui.ManageSpaceActivity.java
com.salesforce.androidsdk.ui.OAuthWebviewHelper.java
com.salesforce.androidsdk.ui.PasscodeActivity.java
com.salesforce.androidsdk.ui.SalesforceAccountRadioButton.java
com.salesforce.androidsdk.ui.SalesforceR.java
com.salesforce.androidsdk.ui.SalesforceServerRadioButton.java
com.salesforce.androidsdk.ui.ServerPickerActivity.java
com.salesforce.androidsdk.ui.sfhybrid.SalesforceDroidGapActivity.java
com.salesforce.androidsdk.ui.sfhybrid.SalesforceGapViewClient.java
com.salesforce.androidsdk.ui.sfnative.SalesforceActivity.java
com.salesforce.androidsdk.ui.sfnative.SalesforceExpandableListActivity.java
com.salesforce.androidsdk.ui.sfnative.SalesforceListActivity.java
com.salesforce.androidsdk.util.EventsListenerQueue.java
com.salesforce.androidsdk.util.EventsObservable.java
com.salesforce.androidsdk.util.EventsObserver.java
com.salesforce.androidsdk.util.ForceAppInstrumentationTestCase.java
com.salesforce.androidsdk.util.HybridInstrumentationTestCase.java
com.salesforce.androidsdk.util.JSTestCase.java
com.salesforce.androidsdk.util.JUnitReportTestRunner.java
com.salesforce.androidsdk.util.LogUtil.java
com.salesforce.androidsdk.util.NativeInstrumentationTestCase.java
com.salesforce.androidsdk.util.TimeLimitedTestRunner.java
com.salesforce.androidsdk.util.TokenRevocationReceiver.java
com.salesforce.androidsdk.util.UriFragmentParser.java
com.salesforce.androidsdk.util.UserSwitchReceiver.java
com.salesforce.samples.accounteditor.AccountEditorApp.java
com.salesforce.samples.accounteditor.KeyImpl.java
com.salesforce.samples.analyticsapp.AnalyticsApp.java
com.salesforce.samples.analyticsapp.GraphActivity.java
com.salesforce.samples.analyticsapp.KeyImpl.java
com.salesforce.samples.analyticsapp.MainActivity.java
com.salesforce.samples.analyticsapp.PieChart.java
com.salesforce.samples.contactexplorer.ContactExplorerApp.java
com.salesforce.samples.contactexplorer.KeyImpl.java
com.salesforce.samples.hybridfileexplorer.HybridFileExplorerApp.java
com.salesforce.samples.hybridfileexplorer.KeyImpl.java
com.salesforce.samples.smartstoreexplorer.KeyImpl.java
com.salesforce.samples.smartstoreexplorer.SmartStoreExplorerApp.java
com.salesforce.samples.vfconnector.KeyImpl.java
com.salesforce.samples.vfconnector.VFConnectorApp.java