Search in sources :

Example 1 with ModelAssociation

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

the class AppSyncGraphQLRequestFactory method getMapOfFieldNameAndValues.

private static Map<String, Object> getMapOfFieldNameAndValues(@NonNull ModelSchema schema, @NonNull Model instance) throws AmplifyException {
    if (!instance.getClass().getSimpleName().equals(schema.getName())) {
        throw new AmplifyException("The object provided is not an instance of " + schema.getName() + ".", "Please provide an instance of " + schema.getName() + " that matches the schema type.");
    }
    final Map<String, Object> result = new HashMap<>();
    for (ModelField modelField : schema.getFields().values()) {
        if (modelField.isReadOnly()) {
            // Skip read only fields, since they should not be included on the input object.
            continue;
        }
        String fieldName = modelField.getName();
        Object fieldValue = extractFieldValue(fieldName, instance, schema);
        final ModelAssociation association = schema.getAssociations().get(fieldName);
        if (association == null) {
            result.put(fieldName, fieldValue);
        } else if (association.isOwner()) {
            Model target = (Model) Objects.requireNonNull(fieldValue);
            result.put(association.getTargetName(), target.getId());
        }
    // Ignore if field is associated, but is not a "belongsTo" relationship
    }
    /*
         * If the owner field exists on the model, and the value is null, it should be omitted when performing a
         * mutation because the AppSync server will automatically populate it using the authentication token provided
         * in the request header.  The logic below filters out the owner field if null for this scenario.
         */
    for (AuthRule authRule : schema.getAuthRules()) {
        if (AuthStrategy.OWNER.equals(authRule.getAuthStrategy())) {
            String ownerField = authRule.getOwnerFieldOrDefault();
            if (result.containsKey(ownerField) && result.get(ownerField) == null) {
                result.remove(ownerField);
            }
        }
    }
    return result;
}
Also used : AmplifyException(com.amplifyframework.AmplifyException) ModelAssociation(com.amplifyframework.core.model.ModelAssociation) ModelField(com.amplifyframework.core.model.ModelField) HashMap(java.util.HashMap) Model(com.amplifyframework.core.model.Model) AuthRule(com.amplifyframework.core.model.AuthRule)

Example 2 with ModelAssociation

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

the class SQLiteTable method fromSchema.

/**
 * Static method to convert an instance of {@link ModelSchema}
 * into a SQLite table representation. This representation will
 * be useful for storage engine when interacting with SQLite database.
 *
 * Instances of {@link ModelField} inside the schema will be converted
 * to {@link SQLiteColumn} if they meet the following conditions:
 *
 *      1) field is NOT a associated with another model OR,
 *      2) field is the foreign key of relationship
 *
 * The generated SQLite column will encapsulate additional information
 * that is not contained inside {@link ModelField}, such as
 *
 *      1) which table (model) does this field belong to?,
 *      2) what is the corresponding SQLite data type for field type,
 *      3) whether the field represents a foreign key, AND
 *      4) IF it is a foreign key, then which model does it it identify?
 *
 * @param modelSchema An instance of {@link ModelSchema}
 * @return Adapted SQLite table
 */
@NonNull
public static SQLiteTable fromSchema(@NonNull ModelSchema modelSchema) {
    Objects.requireNonNull(modelSchema);
    Map<String, ModelAssociation> associations = modelSchema.getAssociations();
    Map<String, SQLiteColumn> sqlColumns = new TreeMap<>();
    for (ModelField modelField : modelSchema.getFields().values()) {
        final ModelAssociation association = associations.get(modelField.getName());
        final boolean isAssociated = association != null;
        // and is NOT the foreign key
        if (isAssociated && !association.isOwner()) {
            continue;
        }
        // All associated fields are also foreign keys at this point
        SQLiteColumn column = SQLiteColumn.builder().name(isAssociated ? association.getTargetName() : modelField.getName()).fieldName(modelField.getName()).tableName(modelSchema.getName()).ownerOf(isAssociated ? association.getAssociatedType() : null).isNonNull(modelField.isRequired()).dataType(sqlTypeFromModelField(modelField)).build();
        sqlColumns.put(modelField.getName(), column);
    }
    return SQLiteTable.builder().name(modelSchema.getName()).columns(sqlColumns).build();
}
Also used : ModelAssociation(com.amplifyframework.core.model.ModelAssociation) ModelField(com.amplifyframework.core.model.ModelField) TreeMap(java.util.TreeMap) NonNull(androidx.annotation.NonNull)

Example 3 with ModelAssociation

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

the class AppSyncRequestFactory method extractFieldLevelData.

private static Map<String, Object> extractFieldLevelData(ModelSchema schema, Model instance) throws AmplifyException {
    final Map<String, Object> result = new HashMap<>();
    for (ModelField modelField : schema.getFields().values()) {
        if (modelField.isReadOnly()) {
            // Skip read only fields, since they should not be included on the input object.
            continue;
        }
        String fieldName = modelField.getName();
        final ModelAssociation association = schema.getAssociations().get(fieldName);
        if (instance instanceof SerializedModel && !((SerializedModel) instance).getSerializedData().containsKey(fieldName)) {
            // Skip fields that are not set, so that they are not set to null in the request.
            continue;
        }
        if (association == null) {
            result.put(fieldName, extractFieldValue(modelField.getName(), instance, schema));
        } else if (association.isOwner()) {
            String targetName = association.getTargetName();
            result.put(targetName, extractAssociateId(modelField, instance, schema));
        }
    // Ignore if field is associated, but is not a "belongsTo" relationship
    }
    return result;
}
Also used : ModelAssociation(com.amplifyframework.core.model.ModelAssociation) ModelField(com.amplifyframework.core.model.ModelField) HashMap(java.util.HashMap) SerializedModel(com.amplifyframework.core.model.SerializedModel)

Example 4 with ModelAssociation

use of com.amplifyframework.core.model.ModelAssociation 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 5 with ModelAssociation

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

the class SQLiteStorageAdapter method createSerializedModel.

/**
 * recursively creates nested SerializedModels from raw data.
 */
private SerializedModel createSerializedModel(ModelSchema modelSchema, Map<String, Object> data) {
    final Map<String, Object> serializedData = new HashMap<>();
    for (Map.Entry<String, Object> entry : data.entrySet()) {
        ModelField field = modelSchema.getFields().get(entry.getKey());
        if (field != null && entry.getValue() != null) {
            if (field.isModel()) {
                ModelAssociation association = modelSchema.getAssociations().get(entry.getKey());
                if (association != null) {
                    String associatedType = association.getAssociatedType();
                    final ModelSchema nestedModelSchema = schemaRegistry.getModelSchemaForModelClass(associatedType);
                    @SuppressWarnings("unchecked") SerializedModel model = createSerializedModel(nestedModelSchema, (Map<String, Object>) entry.getValue());
                    serializedData.put(entry.getKey(), model);
                }
            } else if (field.isCustomType()) {
                if (field.isArray()) {
                    @SuppressWarnings("unchecked") List<Map<String, Object>> listItems = (List<Map<String, Object>>) entry.getValue();
                    List<SerializedCustomType> listOfCustomType = getValueOfListCustomTypeField(field.getTargetType(), listItems);
                    serializedData.put(entry.getKey(), listOfCustomType);
                } else {
                    final CustomTypeSchema nestedCustomTypeSchema = schemaRegistry.getCustomTypeSchemaForCustomTypeClass(field.getTargetType());
                    @SuppressWarnings("unchecked") SerializedCustomType customType = createSerializedCustomType(nestedCustomTypeSchema, (Map<String, Object>) entry.getValue());
                    serializedData.put(entry.getKey(), customType);
                }
            } else {
                serializedData.put(entry.getKey(), entry.getValue());
            }
        }
    }
    return SerializedModel.builder().serializedData(serializedData).modelSchema(modelSchema).build();
}
Also used : CustomTypeSchema(com.amplifyframework.core.model.CustomTypeSchema) ModelAssociation(com.amplifyframework.core.model.ModelAssociation) HashMap(java.util.HashMap) SerializedCustomType(com.amplifyframework.core.model.SerializedCustomType) SerializedModel(com.amplifyframework.core.model.SerializedModel) ModelSchema(com.amplifyframework.core.model.ModelSchema) ModelField(com.amplifyframework.core.model.ModelField) List(java.util.List) ArrayList(java.util.ArrayList) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

ModelAssociation (com.amplifyframework.core.model.ModelAssociation)6 ModelField (com.amplifyframework.core.model.ModelField)5 HashMap (java.util.HashMap)4 ModelSchema (com.amplifyframework.core.model.ModelSchema)3 SerializedModel (com.amplifyframework.core.model.SerializedModel)3 Cursor (android.database.Cursor)1 SQLiteException (android.database.sqlite.SQLiteException)1 NonNull (androidx.annotation.NonNull)1 AmplifyException (com.amplifyframework.AmplifyException)1 AuthRule (com.amplifyframework.core.model.AuthRule)1 CustomTypeSchema (com.amplifyframework.core.model.CustomTypeSchema)1 Model (com.amplifyframework.core.model.Model)1 SchemaRegistry (com.amplifyframework.core.model.SchemaRegistry)1 SerializedCustomType (com.amplifyframework.core.model.SerializedCustomType)1 SQLiteTable (com.amplifyframework.datastore.storage.sqlite.adapter.SQLiteTable)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1 TreeMap (java.util.TreeMap)1