Search in sources :

Example 81 with DataStoreException

use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.

the class SQLiteModelFieldTypeConverter method convertValueFromSource.

@Override
public Object convertValueFromSource(@NonNull Cursor cursor, @NonNull ModelField field) throws DataStoreException {
    final JavaFieldType javaFieldType = TypeConverter.getJavaFieldType(field);
    try {
        // Skip if there is no equivalent column for field in object
        final SQLiteColumn column = columns.get(field.getName());
        if (column == null) {
            LOGGER.verbose(String.format("Column with name %s does not exist", field.getName()));
            return null;
        }
        String columnName = column.getAliasedName();
        if (javaFieldType == JavaFieldType.MODEL) {
            int newInnerModelCount = 1;
            String fieldTargetType = field.getTargetType();
            if (cursorInnerModelCounts.containsKey(fieldTargetType)) {
                Integer currentInnerModelCount = cursorInnerModelCounts.get(fieldTargetType);
                newInnerModelCount += currentInnerModelCount == null ? 0 : currentInnerModelCount;
            }
            cursorInnerModelCounts.put(fieldTargetType, newInnerModelCount);
        }
        if (isInnerModel && cursorInnerModelCounts.containsKey(parentSchema.getName())) {
            Integer modelCount = cursorInnerModelCounts.get(parentSchema.getName());
            if (!Objects.equals(modelCount, 1)) {
                // More than 1 of the model the field belongs to is present in the cursor
                columnName += modelCount;
            }
        }
        final int columnIndex = cursor.getColumnIndexOrThrow(columnName);
        // This check is necessary, because primitive values will return 0 even when null
        if (cursor.isNull(columnIndex)) {
            return null;
        }
        final String valueAsString = cursor.getString(columnIndex);
        LOGGER.verbose(String.format("Attempt to convert value \"%s\" from field %s of type %s in model %s", valueAsString, field.getName(), field.getTargetType(), parentSchema.getName()));
        switch(javaFieldType) {
            case STRING:
                return cursor.getString(columnIndex);
            case MODEL:
                return convertModelAssociationToTarget(cursor, field);
            case ENUM:
                return convertEnumValueToTarget(valueAsString, field);
            case CUSTOM_TYPE:
                return convertCustomTypeToTarget(cursor, field, columnIndex);
            case INTEGER:
                return cursor.getInt(columnIndex);
            case BOOLEAN:
                return cursor.getInt(columnIndex) != 0;
            case FLOAT:
                return cursor.getFloat(columnIndex);
            case DOUBLE:
                return cursor.getDouble(columnIndex);
            case LONG:
                return cursor.getLong(columnIndex);
            case DATE:
                return new Temporal.Date(valueAsString);
            case DATE_TIME:
                return new Temporal.DateTime(valueAsString);
            case TIME:
                return new Temporal.Time(valueAsString);
            case TIMESTAMP:
                return new Temporal.Timestamp(cursor.getLong(columnIndex), TimeUnit.SECONDS);
            default:
                LOGGER.warn(String.format("Field of type %s is not supported. Fallback to null.", javaFieldType));
                return null;
        }
    } catch (Exception exception) {
        throw new DataStoreException(String.format("Error converting field \"%s\" from model \"%s\"", field.getName(), parentSchema.getName()), exception, AmplifyException.REPORT_BUG_TO_AWS_SUGGESTION);
    }
}
Also used : DataStoreException(com.amplifyframework.datastore.DataStoreException) SQLiteColumn(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteColumn) LocalTime(java.time.LocalTime) OffsetTime(java.time.OffsetTime) OffsetDateTime(java.time.OffsetDateTime) JavaFieldType(com.amplifyframework.core.model.types.JavaFieldType) OffsetDateTime(java.time.OffsetDateTime) AmplifyException(com.amplifyframework.AmplifyException) IOException(java.io.IOException) DataStoreException(com.amplifyframework.datastore.DataStoreException)

Example 82 with DataStoreException

use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.

the class SQLiteStorageAdapter method writeData.

private <T extends Model> void writeData(T item, StorageItemChange.Type writeType) throws DataStoreException {
    final String modelName = item.getModelName();
    final ModelSchema modelSchema = schemaRegistry.getModelSchemaForModelClass(modelName);
    final SQLiteTable sqliteTable = SQLiteTable.fromSchema(modelSchema);
    // Generate SQL command for given action
    switch(writeType) {
        case CREATE:
            LOG.verbose("Creating item in " + sqliteTable.getName() + " identified by ID: " + item.getId());
            sqlCommandProcessor.execute(sqlCommandFactory.insertFor(modelSchema, item));
            break;
        case UPDATE:
            LOG.verbose("Updating item in " + sqliteTable.getName() + " identified by ID: " + item.getId());
            sqlCommandProcessor.execute(sqlCommandFactory.updateFor(modelSchema, item));
            break;
        case DELETE:
            LOG.verbose("Deleting item in " + sqliteTable.getName() + " identified by ID: " + item.getId());
            final String primaryKeyName = sqliteTable.getPrimaryKey().getName();
            final QueryPredicate matchId = QueryField.field(modelName, primaryKeyName).eq(item.getId());
            sqlCommandProcessor.execute(sqlCommandFactory.deleteFor(modelSchema, matchId));
            break;
        default:
            throw new DataStoreException("Unexpected change was requested: " + writeType.name(), "Valid storage changes are CREATE, UPDATE, and DELETE.");
    }
}
Also used : ModelSchema(com.amplifyframework.core.model.ModelSchema) DataStoreException(com.amplifyframework.datastore.DataStoreException) QueryPredicate(com.amplifyframework.core.model.query.predicate.QueryPredicate) SQLiteTable(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable)

Example 83 with DataStoreException

use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.

the class SQLiteStorageAdapter method initialize.

/**
 * {@inheritDoc}
 */
@Override
public synchronized void initialize(@NonNull Context context, @NonNull Consumer<List<ModelSchema>> onSuccess, @NonNull Consumer<DataStoreException> onError, @NonNull DataStoreConfiguration dataStoreConfiguration) {
    Objects.requireNonNull(context);
    Objects.requireNonNull(onSuccess);
    Objects.requireNonNull(onError);
    // Create a thread pool large enough to take advantage of parallelization, but small enough to avoid
    // OutOfMemoryError and CursorWindowAllocationException issues.
    this.threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * THREAD_POOL_SIZE_MULTIPLIER);
    this.context = context;
    this.dataStoreConfiguration = dataStoreConfiguration;
    threadPool.submit(() -> {
        try {
            /*
                 * Start with a fresh registry.
                 */
            schemaRegistry.clear();
            /*
                 * Create {@link ModelSchema} objects for the corresponding {@link Model}.
                 * Any exception raised during this when inspecting the Model classes
                 * through reflection will be notified via the `onError` callback.
                 */
            schemaRegistry.register(modelsProvider.modelSchemas(), modelsProvider.customTypeSchemas());
            /*
                 * Create the CREATE TABLE and CREATE INDEX commands for each of the
                 * Models. Instantiate {@link SQLiteStorageHelper} to execute those
                 * create commands.
                 */
            this.sqlCommandFactory = new SQLiteCommandFactory(schemaRegistry, gson);
            CreateSqlCommands createSqlCommands = getCreateCommands(modelsProvider.modelNames());
            sqliteStorageHelper = SQLiteStorageHelper.getInstance(context, databaseName, DATABASE_VERSION, createSqlCommands);
            /*
                 * Create and/or open a database. This also invokes
                 * {@link SQLiteStorageHelper#onCreate(SQLiteDatabase)} which executes the tasks
                 * to create tables and indexes. When the function returns without any exception
                 * being thrown, invoke the `onError` callback.
                 *
                 * Errors are thrown when there is no write permission to the database, no space
                 * left in the database for any write operation and other errors thrown while
                 * creating and opening a database. All errors are passed through the
                 * `onError` callback.
                 *
                 * databaseConnectionHandle represents a connection handle to the database.
                 * All database operations will happen through this handle.
                 */
            databaseConnectionHandle = sqliteStorageHelper.getWritableDatabase();
            /*
                 * Create helper instance that can traverse through model relations.
                 */
            this.sqliteModelTree = new SQLiteModelTree(schemaRegistry, databaseConnectionHandle);
            /*
                 * Create a command processor which runs the actual SQL transactions.
                 */
            this.sqlCommandProcessor = new SQLCommandProcessor(databaseConnectionHandle);
            sqlQueryProcessor = new SqlQueryProcessor(sqlCommandProcessor, sqlCommandFactory, schemaRegistry);
            syncStatus = new SyncStatus(sqlQueryProcessor, dataStoreConfiguration);
            /*
                 * Detect if the version of the models stored in SQLite is different
                 * from the version passed in through {@link ModelProvider#version()}.
                 * Delete the database if there is a version change.
                 */
            toBeDisposed.add(updateModels().subscribe(() -> onSuccess.accept(Immutable.of(new ArrayList<>(schemaRegistry.getModelSchemaMap().values()))), throwable -> onError.accept(new DataStoreException("Error in initializing the SQLiteStorageAdapter", throwable, AmplifyException.TODO_RECOVERY_SUGGESTION))));
        } catch (Exception exception) {
            onError.accept(new DataStoreException("Error in initializing the SQLiteStorageAdapter", exception, "See attached exception"));
        }
    });
}
Also used : ObjectsCompat(androidx.core.util.ObjectsCompat) AmplifyException(com.amplifyframework.AmplifyException) NonNull(androidx.annotation.NonNull) QueryPredicates(com.amplifyframework.core.model.query.predicate.QueryPredicates) ModelProvider(com.amplifyframework.core.model.ModelProvider) StorageItemChange(com.amplifyframework.datastore.storage.StorageItemChange) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) Gson(com.google.gson.Gson) Map(java.util.Map) PublishSubject(io.reactivex.rxjava3.subjects.PublishSubject) QueryOptions(com.amplifyframework.core.model.query.QueryOptions) CustomTypeSchema(com.amplifyframework.core.model.CustomTypeSchema) SerializedModel(com.amplifyframework.core.model.SerializedModel) Immutable(com.amplifyframework.util.Immutable) Set(java.util.Set) Executors(java.util.concurrent.Executors) Logger(com.amplifyframework.logging.Logger) Objects(java.util.Objects) DataStoreException(com.amplifyframework.datastore.DataStoreException) LocalStorageAdapter(com.amplifyframework.datastore.storage.LocalStorageAdapter) List(java.util.List) Cancelable(com.amplifyframework.core.async.Cancelable) SQLiteTable(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable) Disposable(io.reactivex.rxjava3.disposables.Disposable) Context(android.content.Context) SerializedCustomType(com.amplifyframework.core.model.SerializedCustomType) QueryField(com.amplifyframework.core.model.query.predicate.QueryField) Single(io.reactivex.rxjava3.core.Single) ObserveQueryOptions(com.amplifyframework.core.model.query.ObserveQueryOptions) SystemModelsProviderFactory(com.amplifyframework.datastore.model.SystemModelsProviderFactory) HashMap(java.util.HashMap) CustomTypeField(com.amplifyframework.core.model.CustomTypeField) ModelField(com.amplifyframework.core.model.ModelField) ArrayList(java.util.ArrayList) SchemaRegistry(com.amplifyframework.core.model.SchemaRegistry) GsonFactory(com.amplifyframework.util.GsonFactory) HashSet(java.util.HashSet) Consumer(com.amplifyframework.core.Consumer) CompositeDisposable(io.reactivex.rxjava3.disposables.CompositeDisposable) ModelSchema(com.amplifyframework.core.model.ModelSchema) Subject(io.reactivex.rxjava3.subjects.Subject) QueryPredicate(com.amplifyframework.core.model.query.predicate.QueryPredicate) ExecutorService(java.util.concurrent.ExecutorService) Cursor(android.database.Cursor) DataStoreQuerySnapshot(com.amplifyframework.datastore.DataStoreQuerySnapshot) DataStoreConfiguration(com.amplifyframework.datastore.DataStoreConfiguration) Amplify(com.amplifyframework.core.Amplify) CompoundModelProvider(com.amplifyframework.datastore.model.CompoundModelProvider) Iterator(java.util.Iterator) Model(com.amplifyframework.core.model.Model) Completable(io.reactivex.rxjava3.core.Completable) Action(com.amplifyframework.core.Action) Where(com.amplifyframework.core.model.query.Where) ModelAssociation(com.amplifyframework.core.model.ModelAssociation) TimeUnit(java.util.concurrent.TimeUnit) ModelMigrations(com.amplifyframework.datastore.storage.sqlite.migrations.ModelMigrations) VisibleForTesting(androidx.annotation.VisibleForTesting) Collections(java.util.Collections) DataStoreException(com.amplifyframework.datastore.DataStoreException) ArrayList(java.util.ArrayList) AmplifyException(com.amplifyframework.AmplifyException) DataStoreException(com.amplifyframework.datastore.DataStoreException)

Example 84 with DataStoreException

use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.

the class SqlQueryProcessor method queryOfflineData.

<T extends Model> List<T> queryOfflineData(@NonNull Class<T> itemClass, @NonNull QueryOptions options, @NonNull Consumer<DataStoreException> onError) {
    final ModelSchema modelSchema = modelSchemaRegistry.getModelSchemaForModelClass(itemClass.getSimpleName());
    final List<T> models = new ArrayList<>();
    try (Cursor cursor = sqlCommandProcessor.rawQuery(sqlCommandFactory.queryFor(modelSchema, options))) {
        LOG.debug("Querying item for: " + itemClass.getSimpleName());
        final SQLiteModelFieldTypeConverter converter = new SQLiteModelFieldTypeConverter(modelSchema, modelSchemaRegistry, gson);
        if (cursor == null) {
            onError.accept(new DataStoreException("Error in getting a cursor to the table for class: " + itemClass.getSimpleName(), AmplifyException.TODO_RECOVERY_SUGGESTION));
        } else if (cursor.moveToFirst()) {
            do {
                Map<String, Object> map = converter.buildMapForModel(cursor);
                String jsonString = gson.toJson(map);
                models.add(gson.fromJson(jsonString, itemClass));
            } while (cursor.moveToNext());
        }
    } catch (Exception exception) {
        onError.accept(new DataStoreException("Error in querying the model.", exception, "See attached exception for details."));
    }
    return models;
}
Also used : ModelSchema(com.amplifyframework.core.model.ModelSchema) DataStoreException(com.amplifyframework.datastore.DataStoreException) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) Map(java.util.Map) AmplifyException(com.amplifyframework.AmplifyException) DataStoreException(com.amplifyframework.datastore.DataStoreException)

Example 85 with DataStoreException

use of com.amplifyframework.datastore.DataStoreException in project amplify-android by aws-amplify.

the class SyncStatus method get.

/**
 * Method returns sync status.
 * @param modelClassName model class name.
 * @param onObservationError invoked on error.
 * @return returns the sync status of true or false.
 */
public boolean get(@NonNull String modelClassName, @NonNull Consumer<DataStoreException> onObservationError) {
    LastSyncMetadata lastSyncMetadata;
    boolean syncStatus = false;
    try {
        lastSyncMetadata = getLastSyncMetaData(modelClassName, onObservationError);
        if (lastSyncMetadata.getLastSyncTime() != null) {
            syncStatus = (Time.now() - lastSyncMetadata.getLastSyncTime()) < TimeUnit.MINUTES.toMillis(dataStoreConfiguration.getSyncIntervalInMinutes());
        }
    } catch (DataStoreException exception) {
        onObservationError.accept(exception);
    }
    return syncStatus;
}
Also used : LastSyncMetadata(com.amplifyframework.datastore.syncengine.LastSyncMetadata) DataStoreException(com.amplifyframework.datastore.DataStoreException)

Aggregations

DataStoreException (com.amplifyframework.datastore.DataStoreException)89 Test (org.junit.Test)52 BlogOwner (com.amplifyframework.testmodels.commentsblog.BlogOwner)36 Consumer (com.amplifyframework.core.Consumer)32 List (java.util.List)32 Cancelable (com.amplifyframework.core.async.Cancelable)31 Model (com.amplifyframework.core.model.Model)31 ArrayList (java.util.ArrayList)31 AmplifyException (com.amplifyframework.AmplifyException)29 ModelSchema (com.amplifyframework.core.model.ModelSchema)28 Collections (java.util.Collections)28 Action (com.amplifyframework.core.Action)27 QueryPredicate (com.amplifyframework.core.model.query.predicate.QueryPredicate)27 TimeUnit (java.util.concurrent.TimeUnit)25 Post (com.amplifyframework.testmodels.commentsblog.Post)23 PostStatus (com.amplifyframework.testmodels.commentsblog.PostStatus)23 Arrays (java.util.Arrays)23 Assert.assertEquals (org.junit.Assert.assertEquals)23 ObserveQueryOptions (com.amplifyframework.core.model.query.ObserveQueryOptions)22 DataStoreQuerySnapshot (com.amplifyframework.datastore.DataStoreQuerySnapshot)21