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;
}
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();
}
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;
}
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:
}
}
}
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();
}
Aggregations