Skip to content

Commit 9f14dea

Browse files
author
Hui Wu
committed
completes feature.
1 parent 90b2e25 commit 9f14dea

File tree

2 files changed

+118
-8
lines changed

2 files changed

+118
-8
lines changed

firebase-firestore/src/main/java/com/google/firebase/firestore/util/CustomClassMapper.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,7 @@ T deserialize(
758758
}
759759

760760
T instance = newInstance(constructor);
761+
HashSet<String> deserialzedProperties = new HashSet<>();
761762
for (Map.Entry<String, Object> entry : values.entrySet()) {
762763
String propertyName = entry.getKey();
763764
ErrorPath childPath = context.errorPath.child(propertyName);
@@ -772,6 +773,7 @@ T deserialize(
772773
CustomClassMapper.deserializeToType(
773774
entry.getValue(), resolvedType, context.newInstanceWithErrorPath(childPath));
774775
invoke(setter, instance, value);
776+
deserialzedProperties.add(propertyName);
775777
} else if (fields.containsKey(propertyName)) {
776778
Field field = fields.get(propertyName);
777779
Type resolvedType = resolveType(field.getGenericType(), types);
@@ -783,6 +785,7 @@ T deserialize(
783785
} catch (IllegalAccessException e) {
784786
throw new RuntimeException(e);
785787
}
788+
deserialzedProperties.add(propertyName);
786789
} else {
787790
String message =
788791
"No setter/field for " + propertyName + " found on class " + clazz.getName();
@@ -797,9 +800,20 @@ T deserialize(
797800
}
798801
}
799802

800-
// Populate @DocumentId annotated fields. If there is a conflict, @DocumentId annotation will
801-
// override whatever value set earlier with document ID from context.
803+
// Populate @DocumentId annotated fields. If there is a conflict (@DocumentId annotation is
804+
// applied to a property that is already deserialized from the firestore document)
805+
// a runtime exception will be thrown.
802806
for (String docIdPropertyName : documentIdPropertyNames) {
807+
if (deserialzedProperties.contains(docIdPropertyName)) {
808+
String message =
809+
"'"
810+
+ docIdPropertyName
811+
+ "' is found from document "
812+
+ context.documentRef.getPath()
813+
+ ", cannot apply @DocumentId on this property for class "
814+
+ clazz.getName();
815+
throw new RuntimeException(message);
816+
}
803817
ErrorPath childPath = context.errorPath.child(docIdPropertyName);
804818
if (setters.containsKey(docIdPropertyName)) {
805819
Method setter = setters.get(docIdPropertyName);

firebase-firestore/src/test/java/com/google/firebase/firestore/util/MapperTest.java

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.firebase.firestore.DocumentReference;
2525
import com.google.firebase.firestore.Exclude;
2626
import com.google.firebase.firestore.PropertyName;
27+
import com.google.firebase.firestore.TestUtil;
2728
import com.google.firebase.firestore.ThrowOnExtraProperties;
2829
import java.io.Serializable;
2930
import java.util.ArrayList;
@@ -906,8 +907,12 @@ public void setValue(String value) {
906907
}
907908

908909
private static <T> T deserialize(String jsonString, Class<T> clazz) {
910+
return deserialize(jsonString, clazz, null);
911+
}
912+
913+
private static <T> T deserialize(String jsonString, Class<T> clazz, DocumentReference docRef) {
909914
Map<String, Object> json = fromSingleQuotedString(jsonString);
910-
return CustomClassMapper.convertToCustomClass(json, clazz, null);
915+
return CustomClassMapper.convertToCustomClass(json, clazz, docRef);
911916
}
912917

913918
private static Object serialize(Object object) {
@@ -2354,6 +2359,15 @@ private static class DocumentIdOnStringField {
23542359
@DocumentId public String docId = "doc-id";
23552360
}
23562361

2362+
private static class DocumentIdOnStringFieldAsProperty {
2363+
@PropertyName("docIdProperty")
2364+
@DocumentId
2365+
public String docId = "doc-id";
2366+
2367+
@PropertyName("anotherProperty")
2368+
public int someOtherProperty = 0;
2369+
}
2370+
23572371
private static class DocumentIdOnDocRefGetter {
23582372
private DocumentReference docRef;
23592373

@@ -2367,15 +2381,75 @@ public void setDocRef(DocumentReference ref) {
23672381
}
23682382
}
23692383

2370-
private static class DocumentIdOnInheritedDocRefSetter {}
2384+
private static class DocumentIdOnInheritedDocRefSetter extends DocumentIdOnDocRefGetter {
2385+
2386+
private DocumentReference inheritedDocRef;
2387+
2388+
@DocumentId
2389+
public DocumentReference getInheritedDocRef() {
2390+
return inheritedDocRef;
2391+
}
2392+
2393+
public void setInheritedDocRef(DocumentReference ref) {
2394+
inheritedDocRef = ref;
2395+
}
2396+
}
23712397

2372-
private static class DocumentIdOnNestObjects {}
2398+
private static class DocumentIdOnNestedObjects {
2399+
@PropertyName("nestedDocIdHolder")
2400+
public DocumentIdOnStringField nestedDocIdHolder;
2401+
}
23732402

23742403
@Test
2375-
public void documentIdsDeserialize() {}
2404+
public void documentIdsDeserialize() {
2405+
DocumentReference ref = TestUtil.documentReference("coll/doc123");
2406+
2407+
assertEquals("doc123", deserialize("{}", DocumentIdOnStringField.class, ref).docId);
2408+
2409+
DocumentIdOnStringFieldAsProperty target =
2410+
deserialize("{'anotherProperty': 100}", DocumentIdOnStringFieldAsProperty.class, ref);
2411+
assertEquals("doc123", target.docId);
2412+
assertEquals(100, target.someOtherProperty);
2413+
2414+
assertEquals(ref, deserialize("{}", DocumentIdOnDocRefGetter.class, ref).getDocRef());
2415+
2416+
DocumentIdOnInheritedDocRefSetter target1 =
2417+
deserialize("{}", DocumentIdOnInheritedDocRefSetter.class, ref);
2418+
assertEquals(ref, target1.getInheritedDocRef());
2419+
assertEquals(ref, target1.getDocRef());
2420+
2421+
assertEquals(
2422+
"doc123",
2423+
deserialize("{'nestedDocIdHolder': {}}", DocumentIdOnNestedObjects.class, ref)
2424+
.nestedDocIdHolder
2425+
.docId);
2426+
}
23762427

23772428
@Test
2378-
public void documentIdsAreIgnoredWhenSerializing() {}
2429+
public void documentIdsRoundTrip() {
2430+
// Implicitly verifies @DocumentId is ignore during serialization.
2431+
2432+
DocumentReference ref = TestUtil.documentReference("coll/doc123");
2433+
2434+
assertEquals(
2435+
Collections.emptyMap(), serialize(deserialize("{}", DocumentIdOnStringField.class, ref)));
2436+
2437+
assertEquals(
2438+
Collections.singletonMap("anotherProperty", 100),
2439+
serialize(
2440+
deserialize("{'anotherProperty': 100}", DocumentIdOnStringFieldAsProperty.class, ref)));
2441+
2442+
assertEquals(
2443+
Collections.emptyMap(), serialize(deserialize("{}", DocumentIdOnDocRefGetter.class, ref)));
2444+
2445+
assertEquals(
2446+
Collections.emptyMap(),
2447+
serialize(deserialize("{}", DocumentIdOnInheritedDocRefSetter.class, ref)));
2448+
2449+
assertEquals(
2450+
Collections.singletonMap("nestedDocIdHolder", Collections.emptyMap()),
2451+
serialize(deserialize("{'nestedDocIdHolder': {}}", DocumentIdOnNestedObjects.class, ref)));
2452+
}
23792453

23802454
private static class DocumentIdOnStringFieldWithConflict {}
23812455

@@ -2386,5 +2460,27 @@ private static class DocumentIdOnNestObjectStringProperyWithConflict {}
23862460
private static class DocumentIdOnInheritedDocRefSetterWithConflict {}
23872461

23882462
@Test
2389-
public void documentIdsDeserializeConflictThrows() {}
2463+
public void documentIdsDeserializeConflictThrows() {
2464+
DocumentReference ref = TestUtil.documentReference("coll/doc123");
2465+
2466+
assertExceptionContains(
2467+
"cannot apply @DocumentId on this property",
2468+
() -> deserialize("{'docId': 'toBeOverwritten'}", DocumentIdOnStringField.class, ref));
2469+
2470+
assertExceptionContains(
2471+
"cannot apply @DocumentId on this property",
2472+
() ->
2473+
deserialize(
2474+
"{'docIdProperty': 'toBeOverwritten', 'anotherProperty': 100}",
2475+
DocumentIdOnStringFieldAsProperty.class,
2476+
ref));
2477+
2478+
assertExceptionContains(
2479+
"cannot apply @DocumentId on this property",
2480+
() ->
2481+
deserialize(
2482+
"{'nestedDocIdHolder': {'docId': 'toBeOverwritten'}}",
2483+
DocumentIdOnNestedObjects.class,
2484+
ref));
2485+
}
23902486
}

0 commit comments

Comments
 (0)