use of com.amplifyframework.core.model.ModelField 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.ModelField in project amplify-android by aws-amplify.
the class AppSyncRequestFactory method extractFieldValue.
private static Object extractFieldValue(String fieldName, Model instance, ModelSchema schema) throws AmplifyException {
if (instance instanceof SerializedModel) {
SerializedModel serializedModel = (SerializedModel) instance;
Map<String, Object> serializedData = serializedModel.getSerializedData();
ModelField field = schema.getFields().get(fieldName);
Object fieldValue = serializedData.get(fieldName);
if (fieldValue != null && field != null && field.isCustomType()) {
return extractCustomTypeFieldValue(fieldName, serializedData.get(fieldName));
}
return fieldValue;
}
try {
Field privateField = instance.getClass().getDeclaredField(fieldName);
privateField.setAccessible(true);
return privateField.get(instance);
} catch (Exception exception) {
throw new AmplifyException("An invalid field was provided. " + fieldName + " is not present in " + schema.getName(), exception, "Check if this model schema is a correct representation of the fields in the provided Object");
}
}
use of com.amplifyframework.core.model.ModelField in project amplify-android by aws-amplify.
the class PendingMutationPersistentRecordTest method modelSchemaGenerationSucceeds.
/**
* Generation of a {@link ModelSchema} for the {@link PendingMutation.PersistentRecord}
* succeeds.
* @throws AmplifyException from Amplify configuration
*/
@Test
public void modelSchemaGenerationSucceeds() throws AmplifyException {
List<ModelField> fields = Arrays.asList(ModelField.builder().name("id").targetType("ID").isRequired(true).javaClassForValue(String.class).build(), ModelField.builder().name("containedModelId").targetType("String").isRequired(true).javaClassForValue(String.class).build(), ModelField.builder().name("serializedMutationData").targetType("String").isRequired(true).javaClassForValue(String.class).build(), ModelField.builder().name("containedModelClassName").targetType("String").isRequired(true).javaClassForValue(String.class).build());
Map<String, ModelField> expectedFieldsMap = new HashMap<>();
for (ModelField field : fields) {
expectedFieldsMap.put(field.getName(), field);
}
final ModelIndex index = ModelIndex.builder().indexFieldNames(Collections.singletonList("containedModelClassName")).indexName("containedModelClassNameBasedIndex").build();
assertEquals(// Expected
ModelSchema.builder().name("PersistentRecord").pluralName("PersistentRecords").fields(expectedFieldsMap).indexes(Collections.singletonMap("containedModelClassNameBasedIndex", index)).modelClass(PendingMutation.PersistentRecord.class).build(), // Actual
ModelSchema.fromModelClass(PendingMutation.PersistentRecord.class));
}
use of com.amplifyframework.core.model.ModelField 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.ModelField in project amplify-android by aws-amplify.
the class ModelHelper method getValue.
/**
* Uses reflection to get a property value on a <code>Model</code> by its <code>ModelField</code>
* reference. This method prioritizes the property getter and fallback to the field itself
* if a getter doesn't exist.
*
* @param model the model instance
* @param field the model field
* @param <M> the model concrete type
* @return the field value or <code>null</code>
* @throws DataStoreException in case of a error happens during the dynamic reflection calls
*/
public static <M extends Model> Object getValue(M model, ModelField field) throws DataStoreException {
final Class<? extends Model> modelClass = model.getClass();
final String fieldName = field.getName();
final String getterName = "get" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
try {
final Method fieldGetter = modelClass.getMethod(getterName);
return fieldGetter.invoke(model);
} catch (Exception exception) {
LOGGER.verbose(String.format("Could not find %s() on %s. Fallback to direct field access.", getterName, modelClass.getName()));
}
// fallback to direct field access
try {
final Field fieldReference = modelClass.getDeclaredField(fieldName);
fieldReference.setAccessible(true);
return fieldReference.get(model);
} catch (Exception fallbackException) {
throw new DataStoreException("Error when reading the property " + fieldName + " from class " + modelClass.getName(), fallbackException, AmplifyException.REPORT_BUG_TO_AWS_SUGGESTION);
}
}
Aggregations