Skip to content

Commit a45ddb4

Browse files
committed
pr comments
1 parent 0374b7a commit a45ddb4

File tree

5 files changed

+61
-9
lines changed

5 files changed

+61
-9
lines changed

aws-api-appsync/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ dependencies {
3838
testImplementation(libs.test.junit)
3939
testImplementation(libs.test.robolectric)
4040
testImplementation(libs.test.jsonassert)
41+
testImplementation(libs.test.kotest.assertions)
4142
testImplementation(project(":testmodels"))
4243
testImplementation(project(":testutils"))
4344
}

aws-api-appsync/src/main/java/com/amplifyframework/core/model/query/predicate/GsonPredicateAdapters.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ public QueryPredicate deserialize(JsonElement json, Type type, JsonDeserializati
162162
case OPERATION:
163163
return gson.fromJson(json, QueryPredicateOperation.class);
164164
case GROUP:
165+
// We need to manually deserialize Groups to ensure we handle nested groups
166+
// and update _types correctly.
165167
return deserializeQueryPredicateGroup(jsonObject);
166168
case ALL:
167169
return gson.fromJson(json, MatchAllQueryPredicate.class);
@@ -182,6 +184,8 @@ public JsonElement serialize(QueryPredicate predicate, Type type, JsonSerializat
182184
JsonElement json;
183185
PredicateType predicateType;
184186
if (predicate instanceof QueryPredicateGroup) {
187+
// We need to manually serialize Groups to ensure we handle nested groups and
188+
// update _types correctly.
185189
predicateType = PredicateType.GROUP;
186190
json = serializeQueryPredicateGroup((QueryPredicateGroup) predicate, context);
187191
} else {
@@ -201,19 +205,58 @@ public JsonElement serialize(QueryPredicate predicate, Type type, JsonSerializat
201205
return jsonObject;
202206
}
203207

208+
/**
209+
* Serializes a QueryPredicateGroup to JSON format.
210+
* <p>
211+
* This method is necessary because QueryPredicateGroup contains nested QueryPredicate objects
212+
* that need to be recursively serialized. We cannot use context.serialize() directly on
213+
* QueryPredicateGroup because:
214+
* 1. Using context.serialize() would cause infinite recursion back to this adapter
215+
* 2. We need to manually construct the JSON structure with proper "_type" fields
216+
* <p>
217+
* The method handles:
218+
* - Serializing the group type (AND, OR, NOT)
219+
* - Recursively serializing each nested predicate in the predicates array
220+
* - Maintaining the correct JSON structure expected by the deserializer
221+
*
222+
* @param group The QueryPredicateGroup to serialize
223+
* @param context The serialization context for handling nested QueryOperator objects
224+
* @return JsonElement representing the serialized group
225+
*/
204226
private JsonElement serializeQueryPredicateGroup(QueryPredicateGroup group, JsonSerializationContext context) {
205227
JsonObject jsonObject = new JsonObject();
206228
jsonObject.addProperty("type", group.type().name());
207229

208230
JsonArray predicatesArray = new JsonArray();
209231
for (QueryPredicate predicate : group.predicates()) {
232+
// Recursively serialize nested predicates using this adapter
210233
predicatesArray.add(serialize(predicate, QueryPredicate.class, context));
211234
}
212235
jsonObject.add("predicates", predicatesArray);
213236

214237
return jsonObject;
215238
}
216239

240+
/**
241+
* Deserializes a JSON object into a QueryPredicateGroup.
242+
* <p>
243+
* This method is necessary because QueryPredicateGroup contains nested QueryPredicate objects
244+
* that need to be recursively deserialized. We cannot use context.deserialize() directly
245+
* because:
246+
* 1. Using context.deserialize() would cause infinite recursion back to this adapter
247+
* 2. We need to manually parse the JSON structure and handle nested predicates
248+
* <p>
249+
* The method handles:
250+
* - Parsing the group type (AND, OR, NOT) from the "type" field
251+
* - Recursively deserializing each predicate in the "predicates" array
252+
* - Creating the QueryPredicateGroup with the correct constructor (no builder available)
253+
* <p>
254+
* This is critical for DataStore sync expressions that contain nested predicate groups,
255+
* which caused the "Interfaces can't be instantiated" error before this fix.
256+
*
257+
* @param jsonObject The JSON object containing the group data
258+
* @return QueryPredicateGroup instance with all nested predicates deserialized
259+
*/
217260
private QueryPredicateGroup deserializeQueryPredicateGroup(JsonObject jsonObject) {
218261
QueryPredicateGroup.Type type = QueryPredicateGroup.Type.valueOf(
219262
jsonObject.get("type").getAsString()
@@ -222,10 +265,13 @@ private QueryPredicateGroup deserializeQueryPredicateGroup(JsonObject jsonObject
222265
List<QueryPredicate> predicates = new ArrayList<>();
223266
JsonArray predicatesArray = jsonObject.getAsJsonArray("predicates");
224267
for (JsonElement predicateElement : predicatesArray) {
268+
// Recursively deserialize nested predicates using this adapter
269+
// Note: Passing null for context since we handle recursion manually
225270
QueryPredicate predicate = deserialize(predicateElement, QueryPredicate.class, null);
226271
predicates.add(predicate);
227272
}
228273

274+
// Use constructor since QueryPredicateGroup doesn't have a builder
229275
return new QueryPredicateGroup(type, predicates);
230276
}
231277
}

aws-api-appsync/src/test/java/com/amplifyframework/core/model/query/predicate/GsonPredicateAdaptersTests.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ package com.amplifyframework.core.model.query.predicate
1616

1717
import com.amplifyframework.testmodels.todo.Todo
1818
import com.google.gson.Gson
19-
import org.junit.Assert.assertEquals
19+
import io.kotest.matchers.shouldBe
2020
import org.junit.Test
2121

2222
class GsonPredicateAdaptersTests {
@@ -32,9 +32,9 @@ class GsonPredicateAdaptersTests {
3232
val expectedString = """
3333
{"field":"id","operator":{"value":"123","type":"EQUAL"},"_type":"OPERATION"}
3434
""".replace("\\s".toRegex(), "")
35-
assertEquals(expectedString, queryPredicateString)
35+
queryPredicateString shouldBe expectedString
3636
val deserializedPredicate = gson.fromJson(queryPredicateString, QueryPredicate::class.java)
37-
assertEquals(queryPredicate, deserializedPredicate)
37+
deserializedPredicate shouldBe queryPredicate
3838
}
3939

4040
@Test
@@ -51,9 +51,9 @@ class GsonPredicateAdaptersTests {
5151
"_type":"GROUP"
5252
}
5353
""".replace("\\s".toRegex(), "")
54-
assertEquals(expectedString, queryPredicateString)
54+
queryPredicateString shouldBe expectedString
5555
val deserializedPredicate = gson.fromJson(queryPredicateString, QueryPredicate::class.java)
56-
assertEquals(queryPredicate, deserializedPredicate)
56+
deserializedPredicate shouldBe queryPredicate
5757
}
5858

5959
@Test
@@ -99,8 +99,8 @@ class GsonPredicateAdaptersTests {
9999
"_type": "GROUP"
100100
}
101101
""".replace("\\s".toRegex(), "")
102-
assertEquals(expectedString, queryPredicateString)
102+
queryPredicateString shouldBe expectedString
103103
val deserializedPredicate = gson.fromJson(queryPredicateString, QueryPredicate::class.java)
104-
assertEquals(queryPredicate, deserializedPredicate)
104+
deserializedPredicate shouldBe queryPredicate
105105
}
106106
}

aws-datastore/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ dependencies {
6161
androidTestImplementation(libs.rxjava)
6262
androidTestImplementation(libs.okhttp)
6363
androidTestImplementation(libs.oauth2)
64+
androidTestImplementation(libs.test.kotest.assertions)
65+
6466
}

aws-datastore/src/androidTest/java/com/amplifyframework/datastore/storage/sqlite/SQLiteStorageAdapterCreateTest.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ import androidx.test.core.app.ApplicationProvider
2020
import com.amplifyframework.datastore.storage.SynchronousStorageAdapter
2121
import com.amplifyframework.datastore.syncengine.MigrationFlagsTable
2222
import com.amplifyframework.testmodels.commentsblog.AmplifyModelProvider
23+
import io.kotest.assertions.withClue
24+
import io.kotest.matchers.ints.shouldBePositive
2325
import org.junit.After
24-
import org.junit.Assert
2526
import org.junit.Before
2627
import org.junit.Test
2728

@@ -70,7 +71,9 @@ class SQLiteStorageAdapterCreateTest {
7071
MigrationFlagsTable.CLEARED_V2_30_0_AND_BELOW_GROUP_SYNC_EXPRESSIONS
7172
)
7273
).use { cursor ->
73-
Assert.assertTrue("Migration flag row was not created", cursor.count > 0)
74+
withClue("Migration flag row was not created") {
75+
cursor.count.shouldBePositive()
76+
}
7477
}
7578
} finally {
7679
database.close()

0 commit comments

Comments
 (0)