Skip to content

Commit af527a9

Browse files
authored
Dicts - Add support for insert collections (#7460)
1 parent 827ce4e commit af527a9

File tree

9 files changed

+544
-149
lines changed

9 files changed

+544
-149
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 containing RealmDictionaries.
7+
* Allow `insert` 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: 45 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,45 +1432,9 @@ class RealmProxyClassGenerator(private val processingEnvironment: ProcessingEnvi
14321432
}
14331433

14341434
@Throws(IOException::class)
1435-
private fun emitInsertMethod(writer: JavaWriter) {
1435+
private fun emitInsertInternal(writer: JavaWriter){
14361436
writer.apply {
1437-
val topLevelArgs = arrayOf("Realm", "realm",
1438-
qualifiedJavaClassName.toString(), "object",
1439-
"Map<RealmModel,Long>", "cache")
1440-
val embeddedArgs = arrayOf("Realm", "realm",
1441-
"Table", "parentObjectTable",
1442-
"long", "parentColumnKey",
1443-
"long", "parentObjectKey",
1444-
qualifiedJavaClassName.toString(), "object",
1445-
"Map<RealmModel,Long>", "cache")
1446-
val args = if (metadata.embedded) embeddedArgs else topLevelArgs
1447-
beginMethod("long","insert", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), *args)
1448-
1449-
// Throw if model contains a set field until we add support for it
1450-
if (containsSet(metadata.fields)) {
1451-
emitStatement("throw new UnsupportedOperationException(\"Calls to 'insert' with RealmModels containing RealmSet properties are not supported yet.\")")
1452-
endMethod()
1453-
emitEmptyLine()
1454-
return@apply
1455-
}
1456-
1457-
// If object is already in the Realm there is nothing to update, unless it is an embedded
1458-
// object. In which case we always update the underlying object.
1459-
if (!metadata.embedded) {
1460-
beginControlFlow("if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet\$proxyState().getRealm\$realm() != null && ((RealmObjectProxy) object).realmGet\$proxyState().getRealm\$realm().getPath().equals(realm.getPath()))")
1461-
emitStatement("return ((RealmObjectProxy) object).realmGet\$proxyState().getRow\$realm().getObjectKey()")
1462-
endControlFlow()
1463-
}
1464-
1465-
emitStatement("Table table = realm.getTable(%s.class)", qualifiedJavaClassName)
1466-
emitStatement("long tableNativePtr = table.getNativePtr()")
1467-
emitStatement("%s columnInfo = (%s) realm.getSchema().getColumnInfo(%s.class)", columnInfoClassName(), columnInfoClassName(), qualifiedJavaClassName)
1468-
1469-
if (metadata.hasPrimaryKey()) {
1470-
emitStatement("long pkColumnKey = %s", fieldColKeyVariableReference(metadata.primaryKey))
1471-
}
14721437
addPrimaryKeyCheckIfNeeded(metadata, true, writer)
1473-
14741438
for (field in metadata.fields) {
14751439
val fieldName = field.simpleName.toString()
14761440
val fieldType = QualifiedClassName(field.asType().toString())
@@ -1635,6 +1599,49 @@ class RealmProxyClassGenerator(private val processingEnvironment: ProcessingEnvi
16351599
}
16361600
}
16371601
}
1602+
}
1603+
}
1604+
1605+
@Throws(IOException::class)
1606+
private fun emitInsertMethod(writer: JavaWriter) {
1607+
writer.apply {
1608+
val topLevelArgs = arrayOf("Realm", "realm",
1609+
qualifiedJavaClassName.toString(), "object",
1610+
"Map<RealmModel,Long>", "cache")
1611+
val embeddedArgs = arrayOf("Realm", "realm",
1612+
"Table", "parentObjectTable",
1613+
"long", "parentColumnKey",
1614+
"long", "parentObjectKey",
1615+
qualifiedJavaClassName.toString(), "object",
1616+
"Map<RealmModel,Long>", "cache")
1617+
val args = if (metadata.embedded) embeddedArgs else topLevelArgs
1618+
beginMethod("long","insert", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), *args)
1619+
1620+
// Throw if model contains a set field until we add support for it
1621+
if (containsSet(metadata.fields)) {
1622+
emitStatement("throw new UnsupportedOperationException(\"Calls to 'insert' with RealmModels containing RealmSet properties are not supported yet.\")")
1623+
endMethod()
1624+
emitEmptyLine()
1625+
return@apply
1626+
}
1627+
1628+
// If object is already in the Realm there is nothing to update, unless it is an embedded
1629+
// object. In which case we always update the underlying object.
1630+
if (!metadata.embedded) {
1631+
beginControlFlow("if (object instanceof RealmObjectProxy && !RealmObject.isFrozen(object) && ((RealmObjectProxy) object).realmGet\$proxyState().getRealm\$realm() != null && ((RealmObjectProxy) object).realmGet\$proxyState().getRealm\$realm().getPath().equals(realm.getPath()))")
1632+
emitStatement("return ((RealmObjectProxy) object).realmGet\$proxyState().getRow\$realm().getObjectKey()")
1633+
endControlFlow()
1634+
}
1635+
1636+
emitStatement("Table table = realm.getTable(%s.class)", qualifiedJavaClassName)
1637+
emitStatement("long tableNativePtr = table.getNativePtr()")
1638+
emitStatement("%s columnInfo = (%s) realm.getSchema().getColumnInfo(%s.class)", columnInfoClassName(), columnInfoClassName(), qualifiedJavaClassName)
1639+
1640+
if (metadata.hasPrimaryKey()) {
1641+
emitStatement("long pkColumnKey = %s", fieldColKeyVariableReference(metadata.primaryKey))
1642+
}
1643+
1644+
emitInsertInternal(this)
16381645

16391646
emitStatement("return objKey")
16401647
endMethod()
@@ -1657,14 +1664,6 @@ class RealmProxyClassGenerator(private val processingEnvironment: ProcessingEnvi
16571664
val args = if (metadata.embedded) embeddedArgs else topLevelArgs
16581665

16591666
beginMethod("void", "insert", EnumSet.of(Modifier.PUBLIC, Modifier.STATIC), *args)
1660-
// Throw if model contains a dictionary field until we add support for it
1661-
if (containsDictionary(metadata.fields)) {
1662-
emitStatement("throw new UnsupportedOperationException(\"Calls to 'insert' with RealmModels containing RealmDictionary properties are not supported yet.\")")
1663-
endMethod()
1664-
emitEmptyLine()
1665-
return@apply
1666-
}
1667-
16681667
// Throw if model contains a set field until we add support for it
16691668
if (containsSet(metadata.fields)) {
16701669
emitStatement("throw new UnsupportedOperationException(\"Calls to 'insert' with RealmModels containing RealmSet properties are not supported yet.\")")
@@ -1691,102 +1690,7 @@ class RealmProxyClassGenerator(private val processingEnvironment: ProcessingEnvi
16911690
emitStatement("continue")
16921691
endControlFlow()
16931692

1694-
addPrimaryKeyCheckIfNeeded(metadata, true, writer)
1695-
1696-
for (field in metadata.fields) {
1697-
val fieldName = field.simpleName.toString()
1698-
val fieldType = QualifiedClassName(field.asType().toString())
1699-
val getter = metadata.getInternalGetter(fieldName)
1700-
1701-
if (Utils.isRealmModel(field)) {
1702-
val isEmbedded = Utils.isFieldTypeEmbedded(field.asType(), classCollection)
1703-
1704-
emitEmptyLine()
1705-
emitStatement("%s %sObj = ((%s) object).%s()", fieldType, fieldName, interfaceName, getter)
1706-
beginControlFlow("if (%sObj != null)", fieldName)
1707-
emitStatement("Long cache%1\$s = cache.get(%1\$sObj)", fieldName)
1708-
if (isEmbedded) {
1709-
beginControlFlow("if (cache%s != null)", fieldName)
1710-
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%s.toString())", fieldName)
1711-
nextControlFlow("else")
1712-
emitStatement("cache%1\$s = %2\$s.insert(realm, table, columnInfo.%3\$sColKey, objKey, %3\$sObj, cache)", fieldName, Utils.getProxyClassSimpleName(field), fieldName)
1713-
endControlFlow()
1714-
} else {
1715-
beginControlFlow("if (cache%s == null)", fieldName)
1716-
emitStatement("cache%s = %s.insert(realm, %sObj, cache)", fieldName, Utils.getProxyClassSimpleName(field), fieldName)
1717-
endControlFlow()
1718-
emitStatement("table.setLink(columnInfo.%1\$sColKey, objKey, cache%1\$s, false)", fieldName)
1719-
}
1720-
endControlFlow()
1721-
} else if (Utils.isRealmModelList(field)) {
1722-
val genericType: TypeMirror = Utils.getGenericType(field)!!
1723-
val isEmbedded = Utils.isFieldTypeEmbedded(genericType, classCollection)
1724-
1725-
emitEmptyLine()
1726-
emitStatement("RealmList<%s> %sList = ((%s) object).%s()", genericType, fieldName, interfaceName, getter)
1727-
beginControlFlow("if (%sList != null)", fieldName)
1728-
emitStatement("OsList %1\$sOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.%1\$sColKey)", fieldName)
1729-
beginControlFlow("for (%1\$s %2\$sItem : %2\$sList)", genericType, fieldName)
1730-
emitStatement("Long cacheItemIndex%1\$s = cache.get(%1\$sItem)", fieldName)
1731-
if (isEmbedded) {
1732-
beginControlFlow("if (cacheItemIndex%s != null)", fieldName)
1733-
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: \" + cacheItemIndex%s.toString())", fieldName)
1734-
nextControlFlow("else")
1735-
emitStatement("cacheItemIndex%1\$s = %2\$s.insert(realm, table, columnInfo.%3\$sColKey, objKey, %3\$sItem, cache)", fieldName, Utils.getProxyClassName(QualifiedClassName(genericType.toString())), fieldName)
1736-
endControlFlow()
1737-
} else {
1738-
beginControlFlow("if (cacheItemIndex%s == null)", fieldName)
1739-
emitStatement("cacheItemIndex%1\$s = %2\$s.insert(realm, %1\$sItem, cache)", fieldName, Utils.getProxyClassSimpleName(field))
1740-
endControlFlow()
1741-
emitStatement("%1\$sOsList.addRow(cacheItemIndex%1\$s)", fieldName)
1742-
}
1743-
endControlFlow()
1744-
endControlFlow()
1745-
} else if (Utils.isRealmValueList(field)) {
1746-
val genericType = Utils.getGenericTypeQualifiedName(field)
1747-
val elementTypeMirror = TypeMirrors.getRealmListElementTypeMirror(field)
1748-
emitEmptyLine()
1749-
emitStatement("RealmList<%s> %sList = ((%s) object).%s()", genericType, fieldName, interfaceName, getter)
1750-
beginControlFlow("if (%sList != null)", fieldName)
1751-
emitStatement("OsList %1\$sOsList = new OsList(table.getUncheckedRow(objKey), columnInfo.%1\$sColKey)", fieldName)
1752-
beginControlFlow("for (%1\$s %2\$sItem : %2\$sList)", genericType, fieldName)
1753-
beginControlFlow("if (%1\$sItem == null)", fieldName)
1754-
emitStatement("%1\$sOsList.addNull()", fieldName)
1755-
nextControlFlow("else")
1756-
emitStatement(getStatementForAppendingValueToOsList(fieldName + "OsList", fieldName + "Item", elementTypeMirror))
1757-
endControlFlow()
1758-
endControlFlow()
1759-
endControlFlow()
1760-
} else if (Utils.isRealmAny(field)) {
1761-
emitEmptyLine()
1762-
1763-
emitStatement("RealmAny ${fieldName}RealmAny = ((${interfaceName}) object).${getter}()")
1764-
emitStatement("${fieldName}RealmAny = ProxyUtils.insert(${fieldName}RealmAny, realm, cache)")
1765-
emitStatement("Table.nativeSetRealmAny(tableNativePtr, columnInfo.${fieldName}ColKey, objKey, ${fieldName}RealmAny.getNativePtr(), false)")
1766-
} else if (Utils.isRealmAnyList(field)) {
1767-
emitEmptyLine()
1768-
1769-
emitStatement("RealmList<RealmAny> ${fieldName}UnmanagedList = ((${interfaceName}) object).${getter}()")
1770-
beginControlFlow("if (${fieldName}UnmanagedList != null)")
1771-
emitStatement("OsList ${fieldName}OsList = new OsList(table.getUncheckedRow(objKey), columnInfo.${fieldName}ColKey)")
1772-
beginControlFlow("for (int i = 0; i < ${fieldName}UnmanagedList.size(); i++)")
1773-
emitStatement("RealmAny realmAnyItem = ${fieldName}UnmanagedList.get(i)")
1774-
emitStatement("realmAnyItem = ProxyUtils.insert(realmAnyItem, realm, cache)")
1775-
emitStatement("${fieldName}OsList.addRealmAny(realmAnyItem.getNativePtr())")
1776-
endControlFlow()
1777-
endControlFlow()
1778-
} else if (Utils.isRealmDictionary(field)) {
1779-
// TODO: diictionary
1780-
emitSingleLineComment("TODO: Dictionary")
1781-
} else if (Utils.isRealmSet(field)) {
1782-
// TODO: sets
1783-
emitSingleLineComment("TODO: Set")
1784-
} else {
1785-
if (metadata.primaryKey !== field) {
1786-
setTableValues(writer, fieldType.toString(), fieldName, interfaceName, getter, false)
1787-
}
1788-
}
1789-
}
1693+
emitInsertInternal(this)
17901694
endControlFlow()
17911695
endMethod()
17921696
emitEmptyLine()

0 commit comments

Comments
 (0)