Search in sources :

Example 96 with ModelSchema

use of com.amplifyframework.core.model.ModelSchema in project amplify-android by aws-amplify.

the class CompoundModelProvider method of.

/**
 * Gets an {@link CompoundModelProvider} that provides all of the same models as the
 * constituent {@link ModelProvider} that are provided. The version of the returned
 * {@link CompoundModelProvider} shall be stable UUID hash of the versions of all
 * provided {@link ModelProvider}s.
 * @param modelProviders model providers
 * @return A compound provider, which provides the models of all of the input providers
 */
@NonNull
public static CompoundModelProvider of(@NonNull ModelProvider... modelProviders) {
    final Map<String, ModelSchema> modelSchemaMap = new HashMap<>();
    final Map<String, CustomTypeSchema> customTypeSchemaMap = new HashMap<>();
    StringBuilder componentVersionBuffer = new StringBuilder();
    for (ModelProvider componentProvider : modelProviders) {
        componentVersionBuffer.append(componentProvider.version());
        modelSchemaMap.putAll(componentProvider.modelSchemas());
        customTypeSchemaMap.putAll(componentProvider.customTypeSchemas());
    }
    String version = UUID.nameUUIDFromBytes(componentVersionBuffer.toString().getBytes()).toString();
    SimpleModelProvider delegateProvider = SimpleModelProvider.instance(version, modelSchemaMap, customTypeSchemaMap);
    return new CompoundModelProvider(delegateProvider);
}
Also used : CustomTypeSchema(com.amplifyframework.core.model.CustomTypeSchema) ModelSchema(com.amplifyframework.core.model.ModelSchema) HashMap(java.util.HashMap) ModelProvider(com.amplifyframework.core.model.ModelProvider) NonNull(androidx.annotation.NonNull)

Example 97 with ModelSchema

use of com.amplifyframework.core.model.ModelSchema in project amplify-android by aws-amplify.

the class SQLiteCommandFactory method recursivelyBuildJoins.

/**
 * Recursively build joins for multilevel nested joins.
 */
private void recursivelyBuildJoins(SQLiteTable table, Map<String, List<SQLiteColumn>> columns, StringBuilder joinStatement, Map<String, Integer> tableCount, String tableAlias) {
    // Joins the foreign keys
    // LEFT JOIN if foreign key is optional, INNER JOIN otherwise.
    final Iterator<SQLiteColumn> foreignKeyIterator = table.getForeignKeys().iterator();
    while (foreignKeyIterator.hasNext()) {
        final SQLiteColumn foreignKey = foreignKeyIterator.next();
        final String ownedTableName = foreignKey.getOwnedType();
        final ModelSchema ownedSchema = schemaRegistry.getModelSchemaForModelClass(ownedTableName);
        final SQLiteTable ownedTable = SQLiteTable.fromSchema(ownedSchema);
        int newOwnedTableCount = 1;
        String ownedTableAlias = ownedTableName;
        if (tableCount.containsKey(ownedTableName)) {
            Integer currentOwnedTableCount = tableCount.get(ownedTableName);
            newOwnedTableCount += currentOwnedTableCount == null ? 0 : currentOwnedTableCount;
            ownedTableAlias += newOwnedTableCount;
        }
        tableCount.put(ownedTableName, newOwnedTableCount);
        columns.put(ownedTableAlias, ownedTable.getSortedColumns());
        SqlKeyword joinType = foreignKey.isNonNull() ? SqlKeyword.INNER_JOIN : SqlKeyword.LEFT_JOIN;
        joinStatement.append(joinType).append(SqlKeyword.DELIMITER).append(Wrap.inBackticks(ownedTableName)).append(SqlKeyword.DELIMITER);
        if (!ownedTableName.equals(ownedTableAlias)) {
            joinStatement.append(SqlKeyword.AS).append(SqlKeyword.DELIMITER).append(Wrap.inBackticks(ownedTableAlias)).append(SqlKeyword.DELIMITER);
        }
        // Reference the foreign key and primary key using the corresponding table's alias.
        String foreignKeyName = foreignKey.getQuotedColumnName().replace(table.getName(), tableAlias);
        String ownedTablePrimaryKeyName = ownedTable.getPrimaryKeyColumnName().replace(ownedTableName, ownedTableAlias);
        joinStatement.append(SqlKeyword.ON).append(SqlKeyword.DELIMITER).append(foreignKeyName).append(SqlKeyword.EQUAL).append(ownedTablePrimaryKeyName);
        if (foreignKeyIterator.hasNext()) {
            joinStatement.append(SqlKeyword.DELIMITER);
        }
        // important that this comes last to maintain the order of the joins
        recursivelyBuildJoins(ownedTable, columns, joinStatement, tableCount, ownedTableAlias);
    }
}
Also used : ModelSchema(com.amplifyframework.core.model.ModelSchema) SQLiteColumn(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteColumn) SQLiteTable(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable)

Example 98 with ModelSchema

use of com.amplifyframework.core.model.ModelSchema in project amplify-android by aws-amplify.

the class SQLiteModelFieldTypeConverter method convertModelAssociationToTarget.

private Object convertModelAssociationToTarget(@NonNull Cursor cursor, @NonNull ModelField field) throws DataStoreException {
    // Eager load model if the necessary columns are present inside the cursor.
    // At the time of implementation, cursor should have been joined with these
    // columns IF AND ONLY IF the model is a foreign key to the inner model.
    ModelSchema innerModelSchema = schemaRegistry.getModelSchemaForModelClass(field.getTargetType());
    SQLiteModelFieldTypeConverter nestedModelConverter = new SQLiteModelFieldTypeConverter(innerModelSchema, schemaRegistry, gson, cursorInnerModelCounts);
    return nestedModelConverter.buildMapForModel(cursor);
}
Also used : ModelSchema(com.amplifyframework.core.model.ModelSchema)

Example 99 with ModelSchema

use of com.amplifyframework.core.model.ModelSchema in project amplify-android by aws-amplify.

the class SQLiteModelTree method recurseTree.

private void recurseTree(Map<ModelSchema, Set<String>> map, ModelSchema modelSchema, Collection<String> parentIds) {
    for (ModelAssociation association : modelSchema.getAssociations().values()) {
        switch(association.getName()) {
            case "HasOne":
            case "HasMany":
                // model name
                String childModel = association.getAssociatedType();
                ModelSchema childSchema = registry.getModelSchemaForModelClass(childModel);
                SQLiteTable childTable = SQLiteTable.fromSchema(childSchema);
                String childId;
                String parentId;
                try {
                    childId = childTable.getPrimaryKey().getName();
                    parentId = // get a map of associations
                    childSchema.getAssociations().get(// get @BelongsTo association linked to this field
                    association.getAssociatedName()).getTargetName();
                } catch (NullPointerException unexpectedAssociation) {
                    LOG.warn("Foreign key was not found due to unidirectional relationship without @BelongsTo. " + "Failed to publish cascading mutations.", unexpectedAssociation);
                    return;
                }
                // Collect every children one level deeper than current level
                Set<String> childrenIds = new HashSet<>();
                try (Cursor cursor = queryChildren(childTable.getName(), childId, parentId, parentIds)) {
                    if (cursor != null && cursor.moveToFirst()) {
                        int index = cursor.getColumnIndexOrThrow(childId);
                        do {
                            childrenIds.add(cursor.getString(index));
                        } while (cursor.moveToNext());
                    }
                } catch (SQLiteException exception) {
                    // Don't cut the search short. Populate rest of the tree.
                    LOG.warn("Failed to query children of deleted model(s).", exception);
                }
                // Add queried result to the map
                if (!childrenIds.isEmpty()) {
                    if (!map.containsKey(childSchema)) {
                        map.put(childSchema, childrenIds);
                    } else {
                        map.get(childSchema).addAll(childrenIds);
                    }
                    recurseTree(map, childSchema, childrenIds);
                }
                break;
            case "BelongsTo":
            default:
        }
    }
}
Also used : ModelSchema(com.amplifyframework.core.model.ModelSchema) ModelAssociation(com.amplifyframework.core.model.ModelAssociation) SQLiteTable(com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable) Cursor(android.database.Cursor) SQLiteException(android.database.sqlite.SQLiteException) HashSet(java.util.HashSet)

Example 100 with ModelSchema

use of com.amplifyframework.core.model.ModelSchema in project amplify-android by aws-amplify.

the class SQLiteModelTree method descendantsOf.

/**
 * Returns a map of descendants of a set of models (of same type).
 * A model is a child of its parent if it uses its parent's ID as foreign key.
 * @param root Collection of models to query its descendants of.
 * @return List of models that are descendants of given models. These models will
 *          have the correct model type and ID, but no other field will be populated.
 */
<T extends Model> List<Model> descendantsOf(Collection<T> root) {
    if (Empty.check(root)) {
        return new ArrayList<>();
    }
    Map<ModelSchema, Set<String>> modelMap = new LinkedHashMap<>();
    Model rootModel = root.iterator().next();
    ModelSchema rootSchema = registry.getModelSchemaForModelClass(getModelName(rootModel));
    Set<String> rootIds = new HashSet<>();
    for (T model : root) {
        rootIds.add(model.getId());
    }
    recurseTree(modelMap, rootSchema, rootIds);
    List<Model> descendants = new ArrayList<>();
    for (Map.Entry<ModelSchema, Set<String>> entry : modelMap.entrySet()) {
        ModelSchema schema = entry.getKey();
        for (String id : entry.getValue()) {
            if (rootModel.getClass() == SerializedModel.class) {
                SerializedModel dummyItem = SerializedModel.builder().serializedData(Collections.singletonMap("id", id)).modelSchema(schema).build();
                descendants.add(dummyItem);
            } else {
                // Create dummy model instance using just the ID and model type
                String dummyJson = gson.toJson(Collections.singletonMap("id", id));
                Model dummyItem = gson.fromJson(dummyJson, schema.getModelClass());
                descendants.add(dummyItem);
            }
        }
    }
    return descendants;
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) ArrayList(java.util.ArrayList) SerializedModel(com.amplifyframework.core.model.SerializedModel) LinkedHashMap(java.util.LinkedHashMap) ModelSchema(com.amplifyframework.core.model.ModelSchema) SerializedModel(com.amplifyframework.core.model.SerializedModel) Model(com.amplifyframework.core.model.Model) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) HashSet(java.util.HashSet)

Aggregations

ModelSchema (com.amplifyframework.core.model.ModelSchema)109 Test (org.junit.Test)69 SerializedModel (com.amplifyframework.core.model.SerializedModel)34 BlogOwner (com.amplifyframework.testmodels.commentsblog.BlogOwner)30 Model (com.amplifyframework.core.model.Model)28 DataStoreException (com.amplifyframework.datastore.DataStoreException)26 HashMap (java.util.HashMap)23 ArrayList (java.util.ArrayList)22 SchemaRegistry (com.amplifyframework.core.model.SchemaRegistry)21 AmplifyException (com.amplifyframework.AmplifyException)19 Consumer (com.amplifyframework.core.Consumer)19 List (java.util.List)17 NonNull (androidx.annotation.NonNull)14 Cancelable (com.amplifyframework.core.async.Cancelable)14 TimeUnit (java.util.concurrent.TimeUnit)14 QueryPredicate (com.amplifyframework.core.model.query.predicate.QueryPredicate)13 Action (com.amplifyframework.core.Action)12 ModelWithMetadata (com.amplifyframework.datastore.appsync.ModelWithMetadata)12 Collections (java.util.Collections)12 ModelProvider (com.amplifyframework.core.model.ModelProvider)11