Skip to content

Commit 8f83a97

Browse files
authored
Dicts - dynamic realms (#7471)
1 parent e5ae3aa commit 8f83a97

File tree

14 files changed

+570
-63
lines changed

14 files changed

+570
-63
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
### Enhancements
77
* Allow `insert` and `insertOrUpdate` operations on `RealmObject` or `RealmObject` collections containing `RealmDictionary` or `RealmSet` fields.
8+
* Added support for `RealmDictionary` in `DynamicRealmObject` with `setDictionary(String fieldName, RealmDictionary<?> dictionary)`, `getDictionary(String fieldName, Class<?> primitiveType)`, and `getDictionary(String fieldName)`.
89

910
### Fixed
1011
* Removed wrong `@Nullable` annotation on `RealmQuery.maxRealmAny()`.

realm/realm-library/src/androidTest/kotlin/io/realm/DictionaryTester.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ interface DictionaryTester : GenericTester {
3939
fun values()
4040
fun entrySet()
4141
fun freeze()
42+
fun dynamic()
4243
fun insert()
4344
fun insertList()
4445
fun insertOrUpdate()

realm/realm-library/src/androidTest/kotlin/io/realm/ManagedDictionaryTesters.kt

Lines changed: 156 additions & 0 deletions
Large diffs are not rendered by default.

realm/realm-library/src/androidTest/kotlin/io/realm/ParameterizedDictionaryTests.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ class ParameterizedDictionaryTests(
169169
tester.freeze()
170170
}
171171

172+
@Test
173+
fun dynamic() {
174+
tester.dynamic()
175+
}
176+
172177
@Test
173178
fun insert() {
174179
tester.insert()

realm/realm-library/src/androidTest/kotlin/io/realm/UnmanagedDictionaryTesters.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ class UnmanagedDictionaryTester<T : Any>(
209209
}
210210
}
211211

212+
override fun dynamic() = Unit // Not applicable
212213
override fun insert() = Unit // Not applicable
213214
override fun insertList() = Unit // Not applicable
214215
override fun insertOrUpdate() = Unit // Not applicable

realm/realm-library/src/androidTest/kotlin/io/realm/entities/DictionaryAllTypes.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
public class DictionaryAllTypes extends RealmObject {
3232

33+
public static final String NAME = "DictionaryAllTypes";
3334
public static final String FIELD_STRING_DICTIONARY = "columnStringDictionary";
3435

3536
private RealmDictionary<DogPrimaryKey> columnRealmDictionary;

realm/realm-library/src/main/java/io/realm/DynamicRealmObject.java

Lines changed: 263 additions & 13 deletions
Large diffs are not rendered by default.

realm/realm-library/src/main/java/io/realm/ManagedMapManager.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,14 @@ boolean isNotNullItemTypeValid(@Nullable Object item, Class<?> clazz) {
194194
OsMap getOsMap() {
195195
return mapValueOperator.osMap;
196196
}
197+
198+
String getClassName() {
199+
return typeSelectorForMap.getValueClassName();
200+
}
201+
202+
Class<V> getValueClass() {
203+
return typeSelectorForMap.getValueClass();
204+
}
197205
}
198206

199207
/**

realm/realm-library/src/main/java/io/realm/RealmDictionary.java

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ public RealmDictionary(Map<String, V> map) {
8282
super(getStrategy(valueClass, baseRealm, osMap));
8383
}
8484

85+
/**
86+
* Constructor used by {@code DynamicRealmObject}s.
87+
*
88+
* @param baseRealm
89+
* @param osMap
90+
* @param className
91+
*/
92+
RealmDictionary(BaseRealm baseRealm, OsMap osMap, String className) {
93+
super(getStrategy(className, baseRealm, osMap));
94+
}
95+
8596
// ------------------------------------------
8697
// Private stuff
8798
// ------------------------------------------
@@ -118,7 +129,6 @@ private static <V> ManagedMapStrategy<String, V> getStrategy(Class<V> valueClass
118129
return new ManagedMapStrategy<>(manager);
119130
}
120131

121-
@SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "This function would be used on dynamic realms, not yet implemented")
122132
private static <V> ManagedMapStrategy<String, V> getStrategy(String valueClass,
123133
BaseRealm baseRealm,
124134
OsMap osMap) {
@@ -175,44 +185,41 @@ private static <V> DictionaryManager<V> getManager(Class<V> valueClass,
175185
private static <V> DictionaryManager<V> getManager(String valueClass,
176186
BaseRealm baseRealm,
177187
OsMap osMap) {
178-
TypeSelectorForMap<String, V> typeSelectorForMap = new DynamicSelectorForMap<>(baseRealm, osMap, valueClass);
179188

180189
MapValueOperator<String, ?> mapValueOperator;
181190

182191
if (valueClass.equals(RealmAny.class.getCanonicalName())) {
183-
mapValueOperator = new RealmAnyValueOperator<>(baseRealm, osMap, (TypeSelectorForMap<String, RealmAny>) typeSelectorForMap);
192+
mapValueOperator = new RealmAnyValueOperator<>(baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, RealmAny.class));
184193
} else if (valueClass.equals(Long.class.getCanonicalName())) {
185-
mapValueOperator = new GenericPrimitiveValueOperator<>(Long.class, baseRealm, osMap, (TypeSelectorForMap<String, Long>) typeSelectorForMap, RealmMapEntrySet.IteratorType.LONG);
194+
mapValueOperator = new GenericPrimitiveValueOperator<>(Long.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Long.class), RealmMapEntrySet.IteratorType.LONG);
186195
} else if (valueClass.equals(Float.class.getCanonicalName())) {
187-
mapValueOperator = new GenericPrimitiveValueOperator<>(Float.class, baseRealm, osMap, (TypeSelectorForMap<String, Float>) typeSelectorForMap, RealmMapEntrySet.IteratorType.FLOAT);
196+
mapValueOperator = new GenericPrimitiveValueOperator<>(Float.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Float.class), RealmMapEntrySet.IteratorType.FLOAT);
188197
} else if (valueClass.equals(Double.class.getCanonicalName())) {
189-
mapValueOperator = new GenericPrimitiveValueOperator<>(Double.class, baseRealm, osMap, (TypeSelectorForMap<String, Double>) typeSelectorForMap, RealmMapEntrySet.IteratorType.DOUBLE);
198+
mapValueOperator = new GenericPrimitiveValueOperator<>(Double.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Double.class), RealmMapEntrySet.IteratorType.DOUBLE);
190199
} else if (valueClass.equals(String.class.getCanonicalName())) {
191-
mapValueOperator = new GenericPrimitiveValueOperator<>(String.class, baseRealm, osMap, (TypeSelectorForMap<String, String>) typeSelectorForMap, RealmMapEntrySet.IteratorType.STRING);
200+
mapValueOperator = new GenericPrimitiveValueOperator<>(String.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, String.class), RealmMapEntrySet.IteratorType.STRING);
192201
} else if (valueClass.equals(Boolean.class.getCanonicalName())) {
193-
mapValueOperator = new GenericPrimitiveValueOperator<>(Boolean.class, baseRealm, osMap, (TypeSelectorForMap<String, Boolean>) typeSelectorForMap, RealmMapEntrySet.IteratorType.BOOLEAN);
202+
mapValueOperator = new GenericPrimitiveValueOperator<>(Boolean.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Boolean.class), RealmMapEntrySet.IteratorType.BOOLEAN);
194203
} else if (valueClass.equals(Date.class.getCanonicalName())) {
195-
mapValueOperator = new GenericPrimitiveValueOperator<>(Date.class, baseRealm, osMap, (TypeSelectorForMap<String, Date>) typeSelectorForMap, RealmMapEntrySet.IteratorType.DATE);
204+
mapValueOperator = new GenericPrimitiveValueOperator<>(Date.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Date.class), RealmMapEntrySet.IteratorType.DATE);
196205
} else if (valueClass.equals(Decimal128.class.getCanonicalName())) {
197-
mapValueOperator = new GenericPrimitiveValueOperator<>(Decimal128.class, baseRealm, osMap, (TypeSelectorForMap<String, Decimal128>) typeSelectorForMap, RealmMapEntrySet.IteratorType.DECIMAL128);
206+
mapValueOperator = new GenericPrimitiveValueOperator<>(Decimal128.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Decimal128.class), RealmMapEntrySet.IteratorType.DECIMAL128);
198207
} else if (valueClass.equals(Integer.class.getCanonicalName())) {
199-
mapValueOperator = new IntegerValueOperator<>(baseRealm, osMap, (TypeSelectorForMap<String, Integer>) typeSelectorForMap);
208+
mapValueOperator = new IntegerValueOperator<>(baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Integer.class));
200209
} else if (valueClass.equals(Short.class.getCanonicalName())) {
201-
mapValueOperator = new ShortValueOperator<>(baseRealm, osMap, (TypeSelectorForMap<String, Short>) typeSelectorForMap);
210+
mapValueOperator = new ShortValueOperator<>(baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Short.class));
202211
} else if (valueClass.equals(Byte.class.getCanonicalName())) {
203-
mapValueOperator = new ByteValueOperator<>(baseRealm, osMap, (TypeSelectorForMap<String, Byte>) typeSelectorForMap);
212+
mapValueOperator = new ByteValueOperator<>(baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, Byte.class));
204213
} else if (valueClass.equals(byte[].class.getCanonicalName())) {
205-
mapValueOperator = new GenericPrimitiveValueOperator<>((Class<V>) byte[].class, baseRealm, osMap, typeSelectorForMap, RealmMapEntrySet.IteratorType.BINARY, (EqualsHelper<String, V>) new BinaryEquals<String>());
214+
mapValueOperator = new GenericPrimitiveValueOperator<>(byte[].class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, byte[].class), RealmMapEntrySet.IteratorType.BINARY, (EqualsHelper<String, byte[]>) new BinaryEquals<String>());
206215
} else if (valueClass.equals(ObjectId.class.getCanonicalName())) {
207-
mapValueOperator = new GenericPrimitiveValueOperator<>(ObjectId.class, baseRealm, osMap, (TypeSelectorForMap<String, ObjectId>) typeSelectorForMap, RealmMapEntrySet.IteratorType.OBJECT_ID);
216+
mapValueOperator = new GenericPrimitiveValueOperator<>(ObjectId.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, ObjectId.class), RealmMapEntrySet.IteratorType.OBJECT_ID);
208217
} else if (valueClass.equals(UUID.class.getCanonicalName())) {
209-
mapValueOperator = new GenericPrimitiveValueOperator<>(UUID.class, baseRealm, osMap, (TypeSelectorForMap<String, UUID>) typeSelectorForMap, RealmMapEntrySet.IteratorType.UUID);
218+
mapValueOperator = new GenericPrimitiveValueOperator<>(UUID.class, baseRealm, osMap, new SelectorForMap<>(baseRealm, osMap, String.class, UUID.class), RealmMapEntrySet.IteratorType.UUID);
210219
} else {
211-
throw new IllegalArgumentException("Only Maps of RealmAny or one of the types that can be boxed inside RealmAny can be used.");
220+
mapValueOperator = new RealmModelValueOperator<>(baseRealm, osMap, new DynamicSelectorForMap<>(baseRealm, osMap, valueClass));
212221
}
213222

214-
return new DictionaryManager<>(baseRealm,
215-
(MapValueOperator<String, V>) mapValueOperator,
216-
typeSelectorForMap);
223+
return new DictionaryManager<>(baseRealm, (MapValueOperator<String, V>) mapValueOperator, (TypeSelectorForMap<String, V>) mapValueOperator.typeSelectorForMap);
217224
}
218225
}

realm/realm-library/src/main/java/io/realm/RealmMap.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,14 @@ OsMap getOsMap() {
305305
return mapStrategy.getOsMap();
306306
}
307307

308+
String getValueClassName() {
309+
return mapStrategy.getValueClassName();
310+
}
311+
312+
Class<V> getValueClass() {
313+
return mapStrategy.getValueClass();
314+
}
315+
308316
/**
309317
* Strategy responsible for abstracting the managed/unmanaged logic for maps.
310318
*
@@ -340,6 +348,10 @@ abstract static class MapStrategy<K, V> implements Map<K, V>, ManageableObject,
340348

341349
abstract OsMap getOsMap();
342350

351+
abstract String getValueClassName();
352+
353+
abstract Class<V> getValueClass();
354+
343355
// ------------------------------------------
344356
// Map API
345357
// ------------------------------------------
@@ -514,6 +526,16 @@ protected boolean hasListeners() {
514526
OsMap getOsMap() {
515527
return managedMapManager.getOsMap();
516528
}
529+
530+
@Override
531+
String getValueClassName() {
532+
return managedMapManager.getClassName();
533+
}
534+
535+
@Override
536+
Class<V> getValueClass() {
537+
return managedMapManager.getValueClass();
538+
}
517539
}
518540

519541
/**
@@ -658,5 +680,15 @@ protected boolean hasListeners() {
658680
OsMap getOsMap() {
659681
throw new UnsupportedOperationException("Unmanaged maps aren't represented in native code.");
660682
}
683+
684+
@Override
685+
String getValueClassName() {
686+
throw new UnsupportedOperationException("Unmanaged maps do not support retrieving the value class name.");
687+
}
688+
689+
@Override
690+
Class<V> getValueClass() {
691+
throw new UnsupportedOperationException("Unmanaged maps do not support retrieving the value class.");
692+
}
661693
}
662694
}

0 commit comments

Comments
 (0)