Skip to content

Commit 57defe2

Browse files
authored
Dicts - support insert or update (#7461)
1 parent af527a9 commit 57defe2

File tree

9 files changed

+689
-28
lines changed

9 files changed

+689
-28
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* None.
55

66
### Enhancements
7-
* Allow `insert` RealmObject's or collections of RealmObject's containing RealmDictionaries.
7+
* Allow `insert` and `insertOrUpdate` RealmObject's or collections of RealmObject's containing RealmDictionaries.
88

99
### Fixed
1010
* Removed wrong `@Nullable` annotation on `RealmQuery.maxRealmAny()`.

realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyClassGenerator.kt

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,14 +1712,6 @@ class RealmProxyClassGenerator(private val processingEnvironment: ProcessingEnvi
17121712
val args = if (metadata.embedded) embeddedArgs else topLevelArgs
17131713
beginMethod("long", "insertOrUpdate", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), *args)
17141714

1715-
// Throw if model contains a dictionary field until we add support for it
1716-
if (containsDictionary(metadata.fields)) {
1717-
emitStatement("throw new UnsupportedOperationException(\"Calls to 'insertOrUpdate' with RealmModels containing RealmDictionary properties are not supported yet.\")")
1718-
endMethod()
1719-
emitEmptyLine()
1720-
return@apply
1721-
}
1722-
17231715
// Throw if model contains a set field until we add support for it
17241716
if (containsSet(metadata.fields)) {
17251717
emitStatement("throw new UnsupportedOperationException(\"Calls to 'insertOrUpdate' with RealmModels containing RealmSet properties are not supported yet.\")")
@@ -1862,9 +1854,69 @@ class RealmProxyClassGenerator(private val processingEnvironment: ProcessingEnvi
18621854
endControlFlow()
18631855
endControlFlow()
18641856
endControlFlow()
1865-
} else if (Utils.isRealmDictionary(field)) {
1866-
// TODO: dictionary
1867-
emitSingleLineComment("TODO: Dictionary")
1857+
} else if (Utils.isRealmModelDictionary(field)) {
1858+
val genericType: QualifiedClassName = Utils.getGenericTypeQualifiedName(field)!!
1859+
val dictElementType: TypeMirror = Utils.getGenericType(field)!!
1860+
val isEmbedded = Utils.isFieldTypeEmbedded(dictElementType, classCollection)
1861+
val linkedProxyClass: SimpleClassName = Utils.getDictionaryGenericProxyClassSimpleName(field)
1862+
1863+
emitStatement("RealmDictionary<${genericType}> ${fieldName}UnmanagedDictionary = ((${interfaceName}) object).${getter}()")
1864+
beginControlFlow("if (${fieldName}UnmanagedDictionary != null)")
1865+
emitStatement("OsMap ${fieldName}OsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)")
1866+
emitStatement("java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()")
1867+
beginControlFlow("for (java.util.Map.Entry<String, ${genericType}> entry : entries)")
1868+
emitStatement("String entryKey = entry.getKey()")
1869+
emitStatement("$genericType ${fieldName}UnmanagedEntryValue = entry.getValue()")
1870+
beginControlFlow("if(${fieldName}UnmanagedEntryValue == null)")
1871+
emitStatement("${fieldName}OsMap.put(entryKey, null)")
1872+
nextControlFlow("else")
1873+
// here goes the rest
1874+
emitStatement("Long cacheItemIndex${fieldName} = cache.get(${fieldName}UnmanagedEntryValue)")
1875+
if (isEmbedded) {
1876+
beginControlFlow("if (cacheItemIndex${fieldName} != null)")
1877+
emitStatement("""throw new IllegalArgumentException("Embedded objects can only have one parent pointing to them. This object was already copied, so another object is pointing to it: cache${fieldName}.toString()")""")
1878+
nextControlFlow("else")
1879+
emitStatement("cacheItemIndex${fieldName} = ${linkedProxyClass}.insertOrUpdate(realm, table, columnInfo.${fieldName}ColKey, objKey, ${fieldName}UnmanagedEntryValue, cache)")
1880+
endControlFlow()
1881+
emitStatement("${fieldName}OsMap.putRow(entryKey, cacheItemIndex${fieldName})")
1882+
} else {
1883+
beginControlFlow("if (cacheItemIndex${fieldName} == null)")
1884+
emitStatement("cacheItemIndex${fieldName} = ${linkedProxyClass}.insertOrUpdate(realm, ${fieldName}UnmanagedEntryValue, cache)")
1885+
endControlFlow()
1886+
emitStatement("${fieldName}OsMap.putRow(entryKey, cacheItemIndex${fieldName})")
1887+
}
1888+
endControlFlow()
1889+
endControlFlow()
1890+
endControlFlow()
1891+
} else if (Utils.isRealmValueDictionary(field)) {
1892+
val genericType = Utils.getGenericTypeQualifiedName(field)
1893+
emitEmptyLine()
1894+
emitStatement("RealmDictionary<${genericType}> ${fieldName}UnmanagedDictionary = ((${interfaceName}) object).${getter}()")
1895+
beginControlFlow("if (${fieldName}UnmanagedDictionary != null)", fieldName)
1896+
emitStatement("OsMap ${fieldName}OsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)")
1897+
1898+
emitStatement("java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()")
1899+
beginControlFlow("for (java.util.Map.Entry<String, ${genericType}> entry : entries)")
1900+
emitStatement("String entryKey = entry.getKey()")
1901+
emitStatement("$genericType ${fieldName}UnmanagedEntryValue = entry.getValue()")
1902+
emitStatement("${fieldName}OsMap.put(entryKey, ${fieldName}UnmanagedEntryValue)")
1903+
endControlFlow()
1904+
endControlFlow()
1905+
} else if (Utils.isRealmAnyDictionary(field)) {
1906+
val genericType = Utils.getGenericTypeQualifiedName(field)
1907+
emitStatement("RealmDictionary<RealmAny> ${fieldName}UnmanagedDictionary = ((${interfaceName}) object).${getter}()")
1908+
beginControlFlow("if (${fieldName}UnmanagedDictionary != null)")
1909+
emitStatement("OsMap ${fieldName}OsMap = new OsMap(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)")
1910+
emitStatement("java.util.Set<java.util.Map.Entry<String, ${genericType}>> entries = ${fieldName}UnmanagedDictionary.entrySet()")
1911+
emitStatement("java.util.List<String> keys = new java.util.ArrayList<>()")
1912+
emitStatement("java.util.List<Long> realmAnyPointers = new java.util.ArrayList<>()")
1913+
beginControlFlow("for (java.util.Map.Entry<String, ${genericType}> entry : entries)")
1914+
emitStatement("RealmAny realmAnyItem = entry.getValue()")
1915+
emitStatement("realmAnyItem = ProxyUtils.insertOrUpdate(realmAnyItem, realm, cache)")
1916+
emitStatement("${fieldName}OsMap.putRealmAny(entry.getKey(), realmAnyItem.getNativePtr())")
1917+
endControlFlow()
1918+
endControlFlow()
1919+
emitEmptyLine()
18681920
} else if (Utils.isRealmSet(field)) {
18691921
// TODO: sets
18701922
emitSingleLineComment("TODO: Set")

0 commit comments

Comments
 (0)