content: package im.actor.runtime.clc;
  
  import java.sql.Connection;
  import java.util.List;
  
  import im.actor.runtime.storage.KeyValueRecord;
  import im.actor.runtime.storage.KeyValueStorage;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  /**
   * Created by mohammad on 11/18/15.
   */
  public class ClcKeyValueStorage implements KeyValueStorage {
  
      private static final Logger logger = LoggerFactory.getLogger(ClcKeyValueStorage.class);
      private SQLiteStatementWrapper insertStatement;
      private SQLiteStatementWrapper deleteStatement;
  
      private DBWrapper db;
      private String name;
      private boolean isSqliteChecked = false;
      private String context;
  
      /**
       * Create table in keyvalue storage if does not exist
       *
       * @param db
       * @param name    table name
       * @param context client unique identifier
       */
      public ClcKeyValueStorage(Connection db, String name, String context) {
          this.db = new DBWrapper(db);
          this.name = name;
          this.context = context;
          if (context == null) {
              logger.warn("context is not set");
              this.context = "";
          }
      }
  
      private void checkSqlite() {
          if (!isSqliteChecked) {
              isSqliteChecked = true;
              db.execSQL("CREATE TABLE IF NOT EXISTS \"" + name + "\" (" + //
                      "\"ID\" INTEGER NOT NULL," + // 0: id
                      "\"BYTES\" BLOB NOT NULL," + // 1: bytes
                      "\"CONTEXT\" TEXT NOT NULL," + // 2: context
                      "PRIMARY KEY(\"ID\", \"CONTEXT\"));");
          }
      }
  
      private void checkInsertStatement() {
          if (insertStatement == null) {
              insertStatement = db.compileStatement("INSERT OR REPLACE INTO \"" + name + "\" " +
                      "(\"ID\",\"BYTES\",\"CONTEXT\") VALUES (?,?,?)");
          }
      }
  
      private void checkDeleteStatement() {
          if (deleteStatement == null) {
              deleteStatement = db.compileStatement("DELETE FROM \"" + name + "\" WHERE \"ID\"=? AND \"CONTEXT\"=? ");
          }
      }
  
  
      @Override
      public void addOrUpdateItem(long id, byte[] data) {
          checkSqlite();
          checkInsertStatement();
  
          insertStatement.bindLong(1, id);
          insertStatement.bindBlob(2, data);
          insertStatement.bindString(3, this.context);
          insertStatement.executeInsert();
  
      }
  
      @Override
      public void addOrUpdateItems(List<KeyValueRecord> values) {
          checkSqlite();
          checkInsertStatement();
  
          for (KeyValueRecord r : values) {
              insertStatement.bindLong(1, r.getId());
              insertStatement.bindBlob(2, r.getData());
              insertStatement.bindString(3, this.context);
              insertStatement.executeInsert();
          }
  
      }
  
      @Override
      public void removeItem(long id) {
          checkSqlite();
          checkDeleteStatement();
  
          deleteStatement.bindLong(1, id);
          deleteStatement.bindString(2, this.context);
          deleteStatement.execute();
      }
  
      @Override
      public void removeItems(long[] ids) {
          checkSqlite();
          checkDeleteStatement();
  
          for (long id : ids) {
              deleteStatement.bindLong(1, id);
              deleteStatement.bindString(2, this.context);
              deleteStatement.execute();
          }
  
      }
  
      @Override
      public byte[] loadItem(long key) {
          checkSqlite();
  
          Cursor cursor = db.query("\"" + name + "\"", new String[]{"\"BYTES\""}, "\"ID\" = ? AND \"CONTEXT\"='?' ", new String[]{"" + key, this.context}, null, null, null);
  
          if (cursor == null) {
              return null;
          }
          try {
              if (cursor.moveToNext())
                  return cursor.getBlob("BYTES");
          } finally {
              cursor.close();
          }
          return null;
      }
  
      @Override
      public List<KeyValueRecord> loadItems(long[] keys) {
          return null;
      }
  
      @Override
      public List<KeyValueRecord> loadAllItems() {
          return null;
      }
  
      @Override
      public void clear() {
          checkSqlite();
  
          db.execSQL("DELETE FROM \"" + name + "\"" + " WHERE \"CONTEXT\"='" + this.context + "'");
      }
  
      public void clearAll() {
          checkSqlite();
  
          db.execSQL("DELETE FROM \"" + name + "\"");
      }
  
      public String getContext() {
          return this.context;
      }
  }
  