All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.contentful.vault.SqliteHelper Maven / Gradle / Ivy

There is a newer version: 3.2.6
Show newest version
/*
 * Copyright (C) 2015 Contentful GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License 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 License for the specific language governing permissions and
 * limitations under the License.
 */

package com.contentful.vault;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.io.FileUtils;

import static com.contentful.vault.BaseFields.CREATED_AT;
import static com.contentful.vault.BaseFields.REMOTE_ID;
import static com.contentful.vault.BaseFields.UPDATED_AT;
import static com.contentful.vault.Sql.CREATE_ENTRY_TYPES;
import static com.contentful.vault.Sql.CREATE_SYNC_INFO;
import static com.contentful.vault.Sql.TABLE_ASSETS;
import static com.contentful.vault.Sql.TABLE_ENTRY_TYPES;
import static com.contentful.vault.Sql.TABLE_LINKS;
import static com.contentful.vault.Sql.TABLE_SYNC_INFO;
import static com.contentful.vault.Sql.assetColumnIndex;
import static com.contentful.vault.Sql.createAssets;
import static com.contentful.vault.Sql.createLinks;
import static com.contentful.vault.Sql.escape;
import static com.contentful.vault.Sql.localizeName;
import static com.contentful.vault.Sql.resourceColumnIndex;

final class SqliteHelper extends SQLiteOpenHelper {
  private final Context context;

  private final SpaceHelper spaceHelper;

  public SqliteHelper(Context context, SpaceHelper spaceHelper) {
    super(context, spaceHelper.getDatabaseName(), null, spaceHelper.getDatabaseVersion());
    this.context = context.getApplicationContext();
    this.spaceHelper = spaceHelper;
    copyDatabase();
  }

  @Override public void onCreate(SQLiteDatabase db) {
    db.beginTransaction();
    try {
      execCreate(spaceHelper, db);
      db.setTransactionSuccessful();
    } finally {
      db.endTransaction();
    }
  }

  @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (spaceHelper.getCopyPath() == null) {
      deleteTables(db);
      onCreate(db);
    }
  }

  static void execCreate(SpaceHelper helper, SQLiteDatabase db) {
    db.execSQL(CREATE_ENTRY_TYPES);
    db.execSQL(CREATE_SYNC_INFO);
    for (String code : helper.getLocales()) {
      db.execSQL(createAssets(code));
      db.execSQL(createLinks(code));
    }
    for (ModelHelper modelHelper : helper.getModels().values()) {
      for (String sql : modelHelper.getCreateStatements(helper)) {
        db.execSQL(sql);
      }
    }
  }

  static void clearRecords(SpaceHelper helper, SQLiteDatabase db) {
    db.beginTransaction();
    try {
      db.delete(escape(TABLE_ENTRY_TYPES), null, null);
      db.delete(escape(TABLE_SYNC_INFO), null, null);
      for (String code : helper.getLocales()) {
        db.delete(escape(localizeName(TABLE_ASSETS, code)), null, null);
        db.delete(escape(localizeName(TABLE_LINKS, code)), null, null);

        for (ModelHelper modelHelper : helper.getModels().values()) {
          db.delete(escape(localizeName(modelHelper.getTableName(), code)), null, null);
        }
      }
      db.setTransactionSuccessful();
    } finally {
      db.endTransaction();
    }
  }

  static void deleteTables(SQLiteDatabase db) {
    String[] columns = new String[] { "name" };
    String selection = "type = ? AND name != ?";
    String[] args = new String[] { "table", "android_metadata" };
    Cursor cursor = db.query("sqlite_master", columns, selection, args, null, null, null);
    List tables = null;
    try {
      if (cursor.moveToFirst()) {
        tables = new ArrayList<>();
        do {
          tables.add(cursor.getString(0));
        } while (cursor.moveToNext());
      }
    } finally {
      cursor.close();
    }
    if (tables != null) {
      db.beginTransaction();
      try {
        for (String table : tables) {
          db.execSQL("DROP TABLE " + escape(table));
        }
        db.setTransactionSuccessful();
      } finally {
        db.endTransaction();
      }
    }
  }

  @SuppressWarnings("unchecked")
  public final  T fromCursor(Class clazz, Cursor cursor) {
    T resource = null;
    if (Asset.class.equals(clazz)) {
      resource = (T) assetFromCursor(cursor);
    } else {
      ModelHelper modelHelper = spaceHelper.getModels().get(clazz);
      if (modelHelper != null) {
        resource = (T) modelHelper.fromCursor(cursor);
      }
    }
    if (resource != null) {
      resource.setRemoteId(cursor.getString(resourceColumnIndex(REMOTE_ID)));
      resource.setCreatedAt(cursor.getString(resourceColumnIndex(CREATED_AT)));
      resource.setUpdatedAt(cursor.getString(resourceColumnIndex(UPDATED_AT)));
    }
    return resource;
  }

  @SuppressWarnings("unchecked")
  private static Asset assetFromCursor(Cursor cursor) {
    String remoteId = cursor.getString(resourceColumnIndex(REMOTE_ID));
    String url = cursor.getString(assetColumnIndex(Asset.Fields.URL));
    String mimeType = cursor.getString(assetColumnIndex(Asset.Fields.MIME_TYPE));
    String title = cursor.getString(assetColumnIndex(Asset.Fields.TITLE));
    String description = cursor.getString(assetColumnIndex(Asset.Fields.DESCRIPTION));
    HashMap fileMap = null;
    byte[] fileBlob = cursor.getBlob(assetColumnIndex(Asset.Fields.FILE));

    if (fileBlob != null && fileBlob.length > 0) {
      try {
        fileMap = BlobUtils.fromBlob(HashMap.class, fileBlob);
      } catch (IOException e) {
        throw new RuntimeException("Failed while deserializing file map for asset '" +
            remoteId + "'.");
      } catch (ClassNotFoundException e) {
        throw new RuntimeException(e);
      }
    }

    return Asset.builder()
        .setUrl(url)
        .setMimeType(mimeType)
        .setTitle(title)
        .setDescription(description)
        .setFile(fileMap)
        .build();
  }

  public SpaceHelper getSpaceHelper() {
    return spaceHelper;
  }

  private void copyDatabase() {
    String copyPath = spaceHelper.getCopyPath();
    if (copyPath == null) {
      return;
    }

    final File dbPath = context.getDatabasePath(spaceHelper.getDatabaseName());
    if (!isPendingCopy(dbPath)) {
      return;
    }

    if (dbPath.exists()) {
      dbPath.delete();
    } else {
      dbPath.getParentFile().mkdirs();
    }

    try {
      FileUtils.copyInputStreamToFile(context.getAssets().open(copyPath), dbPath);
    } catch (IOException e) {
      throw new RuntimeException("Failure while attempting to copy '" + copyPath + "'.", e);
    }
  }

  private boolean isPendingCopy(File dbPath) {
    boolean result = false;
    if (dbPath.exists()) {
      SQLiteDatabase db =
          context.openOrCreateDatabase(spaceHelper.getDatabaseName(), Context.MODE_PRIVATE, null);
      try {
        if (spaceHelper.getDatabaseVersion() > db.getVersion()) {
          result = true;
        }
      } finally {
        db.close();
      }
    } else {
      result = true;
    }
    return result;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy