diff --git a/realm/realm-library/src/androidTest/java/io/realm/DynamicRealmObjectTests.java b/realm/realm-library/src/androidTest/java/io/realm/DynamicRealmObjectTests.java index c87b63b0ce..5622d2dda7 100644 --- a/realm/realm-library/src/androidTest/java/io/realm/DynamicRealmObjectTests.java +++ b/realm/realm-library/src/androidTest/java/io/realm/DynamicRealmObjectTests.java @@ -95,6 +95,13 @@ public void setUp() { typedObj.setFieldDate(new Date(1000)); typedObj.setFieldObject(typedObj); typedObj.getFieldList().add(typedObj); + typedObj.getFieldIntegerList().add(1); + typedObj.getFieldStringList().add("str"); + typedObj.getFieldBooleanList().add(true); + typedObj.getFieldFloatList().add(1.23F); + typedObj.getFieldDoubleList().add(1.234D); + typedObj.getFieldBinaryList().add(new byte[] {1, 2, 3}); + typedObj.getFieldDateList().add(new Date(1000)); dObjTyped = new DynamicRealmObject(typedObj); realm.commitTransaction(); @@ -114,15 +121,16 @@ public void tearDown() { // Types supported by the DynamicRealmObject. private enum SupportedType { - BOOLEAN, SHORT, INT, LONG, BYTE, FLOAT, DOUBLE, STRING, BINARY, DATE, OBJECT, LIST + BOOLEAN, SHORT, INT, LONG, BYTE, FLOAT, DOUBLE, STRING, BINARY, DATE, OBJECT, LIST, + LIST_INTEGER, LIST_STRING, LIST_BOOLEAN, LIST_FLOAT, LIST_DOUBLE, LIST_BINARY, LIST_DATE } private enum ThreadConfinedMethods { GET_BOOLEAN, GET_BYTE, GET_SHORT, GET_INT, GET_LONG, GET_FLOAT, GET_DOUBLE, - GET_BLOB, GET_STRING, GET_DATE, GET_OBJECT, GET_LIST, GET, + GET_BLOB, GET_STRING, GET_DATE, GET_OBJECT, GET_LIST, GET_PRIMITIVE_LIST, GET, SET_BOOLEAN, SET_BYTE, SET_SHORT, SET_INT, SET_LONG, SET_FLOAT, SET_DOUBLE, - SET_BLOB, SET_STRING, SET_DATE, SET_OBJECT, SET_LIST, SET, + SET_BLOB, SET_STRING, SET_DATE, SET_OBJECT, SET_LIST, SET_PRIMITIVE_LIST, SET, IS_NULL, SET_NULL, @@ -134,33 +142,35 @@ private enum ThreadConfinedMethods { @SuppressWarnings({"ResultOfMethodCallIgnored", "EqualsWithItself", "SelfEquals"}) private static void callThreadConfinedMethod(DynamicRealmObject obj, ThreadConfinedMethods method) { switch (method) { - case GET_BOOLEAN: obj.getBoolean(AllJavaTypes.FIELD_BOOLEAN); break; - case GET_BYTE: obj.getByte(AllJavaTypes.FIELD_BYTE); break; - case GET_SHORT: obj.getShort(AllJavaTypes.FIELD_SHORT); break; - case GET_INT: obj.getInt(AllJavaTypes.FIELD_INT); break; - case GET_LONG: obj.getLong(AllJavaTypes.FIELD_LONG); break; - case GET_FLOAT: obj.getFloat(AllJavaTypes.FIELD_FLOAT); break; - case GET_DOUBLE: obj.getDouble(AllJavaTypes.FIELD_DOUBLE); break; - case GET_BLOB: obj.getBlob(AllJavaTypes.FIELD_BINARY); break; - case GET_STRING: obj.getString(AllJavaTypes.FIELD_STRING); break; - case GET_DATE: obj.getDate(AllJavaTypes.FIELD_DATE); break; - case GET_OBJECT: obj.getObject(AllJavaTypes.FIELD_OBJECT); break; - case GET_LIST: obj.getList(AllJavaTypes.FIELD_LIST); break; - case GET: obj.get(AllJavaTypes.FIELD_LONG); break; - - case SET_BOOLEAN: obj.setBoolean(AllJavaTypes.FIELD_BOOLEAN, true); break; - case SET_BYTE: obj.setByte(AllJavaTypes.FIELD_BYTE, (byte) 1); break; - case SET_SHORT: obj.setShort(AllJavaTypes.FIELD_SHORT, (short) 1); break; - case SET_INT: obj.setInt(AllJavaTypes.FIELD_INT, 1); break; - case SET_LONG: obj.setLong(AllJavaTypes.FIELD_LONG, 1L); break; - case SET_FLOAT: obj.setFloat(AllJavaTypes.FIELD_FLOAT, 1F); break; - case SET_DOUBLE: obj.setDouble(AllJavaTypes.FIELD_DOUBLE, 1D); break; - case SET_BLOB: obj.setBlob(AllJavaTypes.FIELD_BINARY, new byte[] {1, 2, 3}); break; - case SET_STRING: obj.setString(AllJavaTypes.FIELD_STRING, "12345"); break; - case SET_DATE: obj.setDate(AllJavaTypes.FIELD_DATE, new Date(1L)); break; - case SET_OBJECT: obj.setObject(AllJavaTypes.FIELD_OBJECT, obj); break; - case SET_LIST: obj.setList(AllJavaTypes.FIELD_LIST, new RealmList<>(obj)); break; - case SET: obj.set(AllJavaTypes.FIELD_LONG, 1L); break; + case GET_BOOLEAN: obj.getBoolean(AllJavaTypes.FIELD_BOOLEAN); break; + case GET_BYTE: obj.getByte(AllJavaTypes.FIELD_BYTE); break; + case GET_SHORT: obj.getShort(AllJavaTypes.FIELD_SHORT); break; + case GET_INT: obj.getInt(AllJavaTypes.FIELD_INT); break; + case GET_LONG: obj.getLong(AllJavaTypes.FIELD_LONG); break; + case GET_FLOAT: obj.getFloat(AllJavaTypes.FIELD_FLOAT); break; + case GET_DOUBLE: obj.getDouble(AllJavaTypes.FIELD_DOUBLE); break; + case GET_BLOB: obj.getBlob(AllJavaTypes.FIELD_BINARY); break; + case GET_STRING: obj.getString(AllJavaTypes.FIELD_STRING); break; + case GET_DATE: obj.getDate(AllJavaTypes.FIELD_DATE); break; + case GET_OBJECT: obj.getObject(AllJavaTypes.FIELD_OBJECT); break; + case GET_LIST: obj.getList(AllJavaTypes.FIELD_LIST); break; + case GET_PRIMITIVE_LIST: obj.getList(AllJavaTypes.FIELD_STRING_LIST, String.class); break; + case GET: obj.get(AllJavaTypes.FIELD_LONG); break; + + case SET_BOOLEAN: obj.setBoolean(AllJavaTypes.FIELD_BOOLEAN, true); break; + case SET_BYTE: obj.setByte(AllJavaTypes.FIELD_BYTE, (byte) 1); break; + case SET_SHORT: obj.setShort(AllJavaTypes.FIELD_SHORT, (short) 1); break; + case SET_INT: obj.setInt(AllJavaTypes.FIELD_INT, 1); break; + case SET_LONG: obj.setLong(AllJavaTypes.FIELD_LONG, 1L); break; + case SET_FLOAT: obj.setFloat(AllJavaTypes.FIELD_FLOAT, 1F); break; + case SET_DOUBLE: obj.setDouble(AllJavaTypes.FIELD_DOUBLE, 1D); break; + case SET_BLOB: obj.setBlob(AllJavaTypes.FIELD_BINARY, new byte[] {1, 2, 3}); break; + case SET_STRING: obj.setString(AllJavaTypes.FIELD_STRING, "12345"); break; + case SET_DATE: obj.setDate(AllJavaTypes.FIELD_DATE, new Date(1L)); break; + case SET_OBJECT: obj.setObject(AllJavaTypes.FIELD_OBJECT, obj); break; + case SET_LIST: obj.setList(AllJavaTypes.FIELD_LIST, new RealmList<>(obj)); break; + case SET_PRIMITIVE_LIST: obj.setList(AllJavaTypes.FIELD_STRING_LIST,new RealmList("foo")); break; + case SET: obj.set(AllJavaTypes.FIELD_LONG, 1L); break; case IS_NULL: obj.isNull(AllJavaTypes.FIELD_OBJECT); break; case SET_NULL: obj.setNull(AllJavaTypes.FIELD_OBJECT); break; @@ -326,7 +336,16 @@ private static void callGetter(DynamicRealmObject target, SupportedType type, Li case BINARY: target.getBlob(fieldName); break; case DATE: target.getDate(fieldName); break; case OBJECT: target.getObject(fieldName); break; - case LIST: target.getList(fieldName); break; + case LIST: + case LIST_INTEGER: + case LIST_STRING: + case LIST_BOOLEAN: + case LIST_FLOAT: + case LIST_DOUBLE: + case LIST_BINARY: + case LIST_DATE: + target.getList(fieldName); + break; default: fail(); } @@ -450,6 +469,13 @@ private static void callSetter(DynamicRealmObject target, SupportedType type, Li case DATE: target.getDate(fieldName); break; case OBJECT: target.setObject(fieldName, null); target.setObject(fieldName, target); break; case LIST: target.setList(fieldName, new RealmList()); break; + case LIST_INTEGER: target.setList(fieldName, new RealmList(1)); break; + case LIST_STRING: target.setList(fieldName, new RealmList("foo")); break; + case LIST_BOOLEAN: target.setList(fieldName, new RealmList(true)); break; + case LIST_FLOAT: target.setList(fieldName, new RealmList(1.23F)); break; + case LIST_DOUBLE: target.setList(fieldName, new RealmList(1.234D)); break; + case LIST_BINARY: target.setList(fieldName, new RealmList(new byte[]{})); break; + case LIST_DATE: target.setList(fieldName, new RealmList(new Date())); break; default: fail(); } @@ -510,6 +536,13 @@ public void typedGettersAndSetters() { assertEquals(dObj, dObj.getObject(AllJavaTypes.FIELD_OBJECT)); break; case LIST: + case LIST_INTEGER: + case LIST_STRING: + case LIST_BOOLEAN: + case LIST_FLOAT: + case LIST_DOUBLE: + case LIST_BINARY: + case LIST_DATE: // Ignores. See testGetList/testSetList. break; default: @@ -545,6 +578,55 @@ public void setter_null() { } catch (IllegalArgumentException ignored) { } break; + case LIST_INTEGER: + try { + dObj.setNull(NullTypes.FIELD_INTEGER_LIST_NULL); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_STRING: + try { + dObj.setNull(NullTypes.FIELD_STRING_LIST_NULL); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_BOOLEAN: + try { + dObj.setNull(NullTypes.FIELD_BOOLEAN_LIST_NULL); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_FLOAT: + try { + dObj.setNull(NullTypes.FIELD_FLOAT_LIST_NULL); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_DOUBLE: + try { + dObj.setNull(NullTypes.FIELD_DOUBLE_LIST_NULL); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_BINARY: + try { + dObj.setNull(NullTypes.FIELD_BINARY_LIST_NULL); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_DATE: + try { + dObj.setNull(NullTypes.FIELD_DATE_LIST_NULL); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; case BOOLEAN: dObj.setNull(NullTypes.FIELD_BOOLEAN_NULL); assertTrue(dObj.isNull(NullTypes.FIELD_BOOLEAN_NULL)); @@ -606,6 +688,13 @@ public void setter_nullOnRequiredFieldsThrows() { switch (type) { case OBJECT: continue; // Ignore case LIST: fieldName = NullTypes.FIELD_LIST_NULL; break; + case LIST_INTEGER: fieldName = NullTypes.FIELD_INTEGER_LIST_NULL; break; + case LIST_STRING: fieldName = NullTypes.FIELD_STRING_LIST_NULL; break; + case LIST_BOOLEAN: fieldName = NullTypes.FIELD_BOOLEAN_LIST_NULL; break; + case LIST_FLOAT: fieldName = NullTypes.FIELD_FLOAT_LIST_NULL; break; + case LIST_DOUBLE: fieldName = NullTypes.FIELD_DATE_LIST_NULL; break; + case LIST_BINARY: fieldName = NullTypes.FIELD_BINARY_LIST_NULL; break; + case LIST_DATE: fieldName = NullTypes.FIELD_DATE_LIST_NULL; break; case BOOLEAN: fieldName = NullTypes.FIELD_BOOLEAN_NOT_NULL; break; case BYTE: fieldName = NullTypes.FIELD_BYTE_NOT_NULL; break; case SHORT: fieldName = NullTypes.FIELD_SHORT_NOT_NULL; break; @@ -651,6 +740,55 @@ public void typedSetter_null() { } catch (IllegalArgumentException ignored) { } break; + case LIST_INTEGER: + try { + dObj.setList(NullTypes.FIELD_INTEGER_LIST_NULL, null); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_STRING: + try { + dObj.setList(NullTypes.FIELD_STRING_LIST_NULL, null); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_BOOLEAN: + try { + dObj.setList(NullTypes.FIELD_BOOLEAN_LIST_NULL, null); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_FLOAT: + try { + dObj.setList(NullTypes.FIELD_FLOAT_LIST_NULL, null); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_DOUBLE: + try { + dObj.setList(NullTypes.FIELD_DOUBLE_LIST_NULL, null); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_BINARY: + try { + dObj.setList(NullTypes.FIELD_BINARY_LIST_NULL, null); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; + case LIST_DATE: + try { + dObj.setList(NullTypes.FIELD_DATE_LIST_NULL, null); + fail(); + } catch (IllegalArgumentException ignored) { + } + break; case DATE: dObj.setDate(NullTypes.FIELD_DATE_NULL, null); assertNull(dObj.getDate(NullTypes.FIELD_DATE_NULL)); @@ -885,6 +1023,21 @@ public void setList_wrongTypeThrows() { dObjTyped.setList(AllJavaTypes.FIELD_LIST, wrongDynamicList); } + @Test + public void setList_objectsOwnList() { + dynamicRealm.beginTransaction(); + + // Test model classes + int originalSize = dObjDynamic.getList(AllJavaTypes.FIELD_LIST).size(); + dObjDynamic.setList(AllJavaTypes.FIELD_LIST, dObjDynamic.getList(AllJavaTypes.FIELD_LIST)); + assertEquals(originalSize, dObjDynamic.getList(AllJavaTypes.FIELD_LIST).size()); + + // Smoke test value lists + originalSize = dObjDynamic.getList(AllJavaTypes.FIELD_STRING_LIST, String.class).size(); + dObjDynamic.setList(AllJavaTypes.FIELD_STRING_LIST, dObjDynamic.getList(AllJavaTypes.FIELD_STRING_LIST, String.class)); + assertEquals(originalSize, dObjDynamic.getList(AllJavaTypes.FIELD_STRING_LIST, String.class).size()); + } + @Test public void untypedSetter_listWrongTypeThrows() { realm.beginTransaction(); @@ -909,6 +1062,7 @@ public void untypedSetter_listMixedTypesThrows() { // List is not a simple getter, tests separately. @Test public void getList() { + // FIXME Also fix primitive lists realm.beginTransaction(); AllTypes obj = realm.createObject(AllTypes.class); Dog dog = realm.createObject(Dog.class); @@ -977,7 +1131,7 @@ public void untypedGetterSetter() { dObj.set(AllJavaTypes.FIELD_OBJECT, dObj); assertEquals(dObj, dObj.get(AllJavaTypes.FIELD_OBJECT)); break; - case LIST: + case LIST: { RealmList newList = new RealmList(); newList.add(dObj); dObj.set(AllJavaTypes.FIELD_LIST, newList); @@ -985,6 +1139,63 @@ public void untypedGetterSetter() { assertEquals(1, list.size()); assertEquals(dObj, list.get(0)); break; + } + case LIST_INTEGER: { + RealmList newList = new RealmList<>(null, 1); + dObj.set(AllJavaTypes.FIELD_INTEGER_LIST, newList); + RealmList list = dObj.getList(AllJavaTypes.FIELD_INTEGER_LIST, Integer.class); + assertEquals(2, list.size()); + assertArrayEquals(newList.toArray(), list.toArray()); + break; + } + case LIST_STRING: { + RealmList newList = new RealmList<>(null, "Foo"); + dObj.set(AllJavaTypes.FIELD_STRING_LIST, newList); + RealmList list = dObj.getList(AllJavaTypes.FIELD_STRING_LIST, String.class); + assertEquals(2, list.size()); + assertArrayEquals(newList.toArray(), list.toArray()); + break; + } + case LIST_BOOLEAN: { + RealmList newList = new RealmList<>(null, true); + dObj.set(AllJavaTypes.FIELD_BOOLEAN_LIST, newList); + RealmList list = dObj.getList(AllJavaTypes.FIELD_BOOLEAN_LIST, Boolean.class); + assertEquals(2, list.size()); + assertArrayEquals(newList.toArray(), list.toArray()); + break; + } + case LIST_FLOAT: { + RealmList newList = new RealmList<>(null, 1.23F); + dObj.set(AllJavaTypes.FIELD_FLOAT_LIST, newList); + RealmList list = dObj.getList(AllJavaTypes.FIELD_FLOAT_LIST, Float.class); + assertEquals(2, list.size()); + assertArrayEquals(newList.toArray(), list.toArray()); + break; + } + case LIST_DOUBLE: { + RealmList newList = new RealmList<>(null, 1.24D); + dObj.set(AllJavaTypes.FIELD_DOUBLE_LIST, newList); + RealmList list = dObj.getList(AllJavaTypes.FIELD_DOUBLE_LIST, Double.class); + assertEquals(2, list.size()); + assertArrayEquals(newList.toArray(), list.toArray()); + break; + } + case LIST_BINARY: { + RealmList newList = new RealmList<>(null, new byte[] {1, 2, 3}); + dObj.set(AllJavaTypes.FIELD_BINARY_LIST, newList); + RealmList list = dObj.getList(AllJavaTypes.FIELD_BINARY_LIST, byte[].class); + assertEquals(2, list.size()); + assertArrayEquals(newList.toArray(), list.toArray()); + break; + } + case LIST_DATE: { + RealmList newList = new RealmList<>(null, new Date(1000)); + dObj.set(AllJavaTypes.FIELD_DATE_LIST, newList); + RealmList list = dObj.getList(AllJavaTypes.FIELD_DATE_LIST, Date.class); + assertEquals(2, list.size()); + assertArrayEquals(newList.toArray(), list.toArray()); + break; + } default: fail(); } @@ -1033,11 +1244,17 @@ public void untypedSetter_usingStringConversion() { // These types don't have a string representation that can be parsed. case OBJECT: case LIST: + case LIST_INTEGER: + case LIST_STRING: + case LIST_BOOLEAN: + case LIST_FLOAT: + case LIST_DOUBLE: + case LIST_BINARY: + case LIST_DATE: case STRING: case BINARY: case BYTE: break; - default: fail("Unknown type: " + type); break; @@ -1081,6 +1298,13 @@ public void untypedSetter_illegalImplicitConversionThrows() { case BYTE: case OBJECT: case LIST: + case LIST_INTEGER: + case LIST_STRING: + case LIST_BOOLEAN: + case LIST_FLOAT: + case LIST_DOUBLE: + case LIST_BINARY: + case LIST_DATE: case STRING: case BINARY: continue; @@ -1200,6 +1424,13 @@ public void getFieldType() { assertEquals(RealmFieldType.INTEGER, dObjTyped.getFieldType(AllJavaTypes.FIELD_SHORT)); assertEquals(RealmFieldType.INTEGER, dObjTyped.getFieldType(AllJavaTypes.FIELD_INT)); assertEquals(RealmFieldType.INTEGER, dObjTyped.getFieldType(AllJavaTypes.FIELD_LONG)); + assertEquals(RealmFieldType.INTEGER_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_INTEGER_LIST)); + assertEquals(RealmFieldType.STRING_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_STRING_LIST)); + assertEquals(RealmFieldType.BOOLEAN_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_BOOLEAN_LIST)); + assertEquals(RealmFieldType.FLOAT_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_FLOAT_LIST)); + assertEquals(RealmFieldType.DOUBLE_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_DOUBLE_LIST)); + assertEquals(RealmFieldType.BINARY_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_BINARY_LIST)); + assertEquals(RealmFieldType.DATE_LIST, dObjTyped.getFieldType(AllJavaTypes.FIELD_DATE_LIST)); } @Test @@ -1253,6 +1484,13 @@ public void toString_nullValues() { assertTrue(str.contains(NullTypes.FIELD_DATE_NULL + ":null")); assertTrue(str.contains(NullTypes.FIELD_OBJECT_NULL + ":null")); assertTrue(str.contains(NullTypes.FIELD_LIST_NULL + ":RealmList[0]")); + assertTrue(str.contains(NullTypes.FIELD_INTEGER_LIST_NULL + ":RealmList[0]")); + assertTrue(str.contains(NullTypes.FIELD_STRING_LIST_NULL + ":RealmList[0]")); + assertTrue(str.contains(NullTypes.FIELD_BOOLEAN_LIST_NULL + ":RealmList[0]")); + assertTrue(str.contains(NullTypes.FIELD_FLOAT_LIST_NULL + ":RealmList[0]")); + assertTrue(str.contains(NullTypes.FIELD_DOUBLE_LIST_NULL + ":RealmList[0]")); + assertTrue(str.contains(NullTypes.FIELD_BINARY_LIST_NULL + ":RealmList[0]")); + assertTrue(str.contains(NullTypes.FIELD_DATE_LIST_NULL + ":RealmList[0]")); } @Test diff --git a/realm/realm-library/src/androidTest/java/io/realm/RealmObjectSchemaTests.java b/realm/realm-library/src/androidTest/java/io/realm/RealmObjectSchemaTests.java index 17ede86e8c..2ac91647bd 100644 --- a/realm/realm-library/src/androidTest/java/io/realm/RealmObjectSchemaTests.java +++ b/realm/realm-library/src/androidTest/java/io/realm/RealmObjectSchemaTests.java @@ -19,7 +19,6 @@ import org.hamcrest.CoreMatchers; import org.junit.After; import org.junit.Before; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -37,8 +36,10 @@ import io.realm.internal.Table; import io.realm.rule.TestRealmConfigurationFactory; +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -758,22 +759,118 @@ public void setRequired_nullValueBecomesDefaultValue() { } } for (FieldListType fieldType : FieldListType.values()) { - String fieldName = fieldType.name(); switch(fieldType) { case LIST: // Skip always non-nullable fields. break; + case STRING_LIST: + checkListValueConversionToDefaultValue(String.class, ""); + break; + case SHORT_LIST: + checkListValueConversionToDefaultValue(Short.class, (short) 0); + break; + case INT_LIST: + checkListValueConversionToDefaultValue(Integer.class, 0); + break; + case LONG_LIST: + checkListValueConversionToDefaultValue(Long.class, 0L); + break; + case BYTE_LIST: + checkListValueConversionToDefaultValue(Byte.class, (byte) 0); + break; + case BOOLEAN_LIST: + checkListValueConversionToDefaultValue(Boolean.class, false); + break; + case FLOAT_LIST: + checkListValueConversionToDefaultValue(Float.class, 0.0F); + break; + case DOUBLE_LIST: + checkListValueConversionToDefaultValue(Double.class, 0.0D); + break; + case BLOB_LIST: + checkListValueConversionToDefaultValue(byte[].class, new byte[0]); + break; + case DATE_LIST: + checkListValueConversionToDefaultValue(Date.class, new Date(0)); + break; + case PRIMITIVE_INT_LIST: + case PRIMITIVE_LONG_LIST: + case PRIMITIVE_BYTE_LIST: + case PRIMITIVE_BOOLEAN_LIST: + case PRIMITIVE_FLOAT_LIST: + case PRIMITIVE_DOUBLE_LIST: + case PRIMITIVE_SHORT_LIST: + // Skip not-nullable fields + break; default: - // Skip not-nullable fields . - if (!fieldType.isNullable()) { - break; - } - // FIXME: Requires DynamicRealm support to be able to create values - // before converting them. See #setRequired_convertPrimitiveLists() + throw new IllegalArgumentException("Unknown type: " + fieldType); } } } + // Checks that null values in a value list are correctly converted to default values + // when field is set to required. + private void checkListValueConversionToDefaultValue(Class type, Object defaultValue) { + schema.addRealmListField("foo", type); + DynamicRealmObject obj = ((DynamicRealm) realm).createObject(schema.getClassName()); + RealmList list = new RealmList<>(); + list.add(null); + obj.setList("foo", list); + assertNull(obj.getList("foo", type).first()); + + // Convert from nullable to required + schema.setRequired("foo", true); + if (defaultValue instanceof byte[]) { + assertArrayEquals((byte[]) defaultValue, (byte[]) obj.getList("foo", type).first()); + } else { + assertEquals(defaultValue, obj.getList("foo", type).first()); + } + + // Convert back again + schema.setRequired("foo", false); + if (defaultValue instanceof byte[]) { + //noinspection ConstantConditions + assertArrayEquals((byte[]) defaultValue, (byte[]) obj.getList("foo", type).first()); + } else { + assertEquals(defaultValue, obj.getList("foo", type).first()); + } + + // Cleanup + schema.removeField("foo"); + } + + // Special test for making sure that binary data in all forms are transformed correctly + // when moving between nullable and required states. + @Test + public void binaryData_nullabilityConversions() { + if (type == ObjectSchemaType.IMMUTABLE) { + return; + } + schema.addRealmListField("foo", byte[].class); + + DynamicRealmObject obj = ((DynamicRealm) realm).createObject(schema.getClassName()); + RealmList list = obj.getList("foo", byte[].class); + assertTrue(list.size() == 0); + + // Initial content (nullable) + list.add(null); + list.add(new byte[] {1, 2, 3}); + assertNull(list.get(0)); + assertArrayEquals(new byte[] {1, 2, 3}, list.get(1)); + + // Transform to required + schema.setRequired("foo", true); + list = obj.getList("foo", byte[].class); + assertEquals(0, list.get(0).length); + assertArrayEquals(new byte[] {1, 2, 3}, list.get(1)); + + // Transform back to nullable + schema.setRequired("foo", false); + list = obj.getList("foo", byte[].class); + assertEquals(0, list.get(0).length); + assertArrayEquals(new byte[] {1, 2, 3}, list.get(1)); + } + @Test public void setRequired_true_onPrimaryKeyField_containsNullValues_shouldThrow() { if (type == ObjectSchemaType.IMMUTABLE) { @@ -916,115 +1013,6 @@ public void setPrimaryKey_trueAndFalse() { } } - // Smoke test to ensure that values are copied and converted correctly when switching - // nullability status on their fields - @Test - public void setRequired_convertPrimitiveLists() { - if (type == ObjectSchemaType.IMMUTABLE) { - return; - } - // TODO Move to DynamicRealm once available. - RealmConfiguration configuration = configFactory.createConfigurationBuilder() - .name("nullableToNonNullable.realm") - .build(); - Realm realm = Realm.getInstance(configuration); - realm.beginTransaction(); - - // Fill all fields with data including null values - AllJavaTypes obj = realm.createObject(AllJavaTypes.class, 1); - for (FieldListType type : FieldListType.values()) { - if (!type.isNullable()) { continue; } // Only test nullable types as they can all be converted - switch (type) { - case STRING_LIST: - obj.getFieldStringList().addAll(Arrays.asList(null, "abc")); - break; - case SHORT_LIST: - obj.getFieldShortList().addAll(Arrays.asList(null, (short) 1)); - break; - case INT_LIST: - obj.getFieldIntegerList().addAll(Arrays.asList(null, 1)); - break; - case LONG_LIST: - obj.getFieldLongList().addAll(Arrays.asList(null, (long) 1)); - break; - case BYTE_LIST: - obj.getFieldByteList().addAll(Arrays.asList(null, (byte) 1)); - break; - case BOOLEAN_LIST: - obj.getFieldBooleanList().addAll(Arrays.asList(null, true)); - break; - case FLOAT_LIST: - obj.getFieldFloatList().addAll(Arrays.asList(null, 1.23F)); - break; - case DOUBLE_LIST: - obj.getFieldDoubleList().addAll(Arrays.asList(null, 1.23D)); - break; - case BLOB_LIST: - obj.getFieldBinaryList().addAll(Arrays.asList(null, new byte[] {1, 2, 3})); - break; - case DATE_LIST: - obj.getFieldDateList().addAll(Arrays.asList(null, new Date())); - break; - default: - throw new IllegalArgumentException("Unknown type: " + type); - } - } - realm.commitTransaction(); - realm.close(); - - DynamicRealm dRealm = DynamicRealm.getInstance(configuration); - schema = dRealm.getSchema().get(AllJavaTypes.class.getSimpleName()); - dRealm.beginTransaction(); - - // First set required (converts all null to default values), then back (= should not change data) - List modes = Arrays.asList(true, false); - - for (Boolean mode : modes) { - for (FieldListType type : FieldListType.values()) { - if (!type.isNullable()) { continue; } // Only test nullable types as they can all be converted - switch (type) { - case STRING_LIST: - schema.setRequired(AllJavaTypes.FIELD_STRING_LIST, mode); - break; - case SHORT_LIST: - schema.setRequired(AllJavaTypes.FIELD_SHORT_LIST, mode); - break; - case INT_LIST: - schema.setRequired(AllJavaTypes.FIELD_INTEGER_LIST, mode); - break; - case LONG_LIST: - schema.setRequired(AllJavaTypes.FIELD_LONG_LIST, mode); - break; - case BYTE_LIST: - schema.setRequired(AllJavaTypes.FIELD_BYTE_LIST, mode); - break; - case BOOLEAN_LIST: - schema.setRequired(AllJavaTypes.FIELD_BOOLEAN_LIST, mode); - break; - case FLOAT_LIST: - schema.setRequired(AllJavaTypes.FIELD_FLOAT_LIST, mode); - break; - case DOUBLE_LIST: - schema.setRequired(AllJavaTypes.FIELD_DOUBLE_LIST, mode); - break; - case BLOB_LIST: - schema.setRequired(AllJavaTypes.FIELD_BINARY_LIST, mode); - break; - case DATE_LIST: - schema.setRequired(AllJavaTypes.FIELD_DATE_LIST, mode); - break; - default: - throw new IllegalArgumentException("Unknown type: " + type); - } - } - } - - // TODO Not possible to check data efficently without DynamicRealm support - // For now, assume that if the test didn't crash that data was moved correctly - dRealm.cancelTransaction(); - dRealm.close(); - } - @Test public void removeNonExistingPrimaryKeyThrows() { if (type == ObjectSchemaType.IMMUTABLE) { diff --git a/realm/realm-library/src/main/cpp/io_realm_internal_Table.cpp b/realm/realm-library/src/main/cpp/io_realm_internal_Table.cpp index 544f3a8c19..3f3f0f0475 100644 --- a/realm/realm-library/src/main/cpp/io_realm_internal_Table.cpp +++ b/realm/realm-library/src/main/cpp/io_realm_internal_Table.cpp @@ -197,7 +197,6 @@ JNIEXPORT jboolean JNICALL Java_io_realm_internal_Table_nativeIsColumnNullable(J return to_jbool(table->is_nullable(S(columnIndex))); // noexcept } // For primitive list - // FIXME: Add test in https://github.com/realm/realm-java/pull/5221 before merging to master return to_jbool(table->get_descriptor()->get_subdescriptor(S(columnIndex))->is_nullable(S(0))); // noexcept } @@ -239,10 +238,8 @@ static void convert_column_to_nullable(JNIEnv* env, Table* old_table, size_t old break; } case type_Binary: { - // Payload copy is needed BinaryData bd = old_table->get_binary(old_col_ndx, i); - std::vector binary_copy(bd.data(), bd.data() + bd.size()); - new_table->set_binary(new_col_ndx, i, BinaryData(binary_copy.data(), binary_copy.size())); + new_table->set_binary(new_col_ndx, i, BinaryData(bd.data(), bd.size())); break; } case type_Int: diff --git a/realm/realm-library/src/main/java/io/realm/DynamicRealmObject.java b/realm/realm-library/src/main/java/io/realm/DynamicRealmObject.java index 012085f1f8..96e93bc735 100644 --- a/realm/realm-library/src/main/java/io/realm/DynamicRealmObject.java +++ b/realm/realm-library/src/main/java/io/realm/DynamicRealmObject.java @@ -17,6 +17,7 @@ import java.util.Arrays; import java.util.Date; +import java.util.Iterator; import java.util.Locale; import javax.annotation.Nonnull; @@ -336,6 +337,8 @@ public DynamicRealmObject getObject(String fieldName) { /** * Returns the {@link RealmList} of {@link DynamicRealmObject}s being linked from the given field. + *

+ * If the list contains primitive types, use {@link #getList(String, Class)} instead. * * @param fieldName the name of the field. * @return the {@link RealmList} data for this field. @@ -346,7 +349,7 @@ public RealmList getList(String fieldName) { long columnIndex = proxyState.getRow$realm().getColumnIndex(fieldName); try { - OsList osList = proxyState.getRow$realm().getList(columnIndex); + OsList osList = proxyState.getRow$realm().getModelList(columnIndex); //noinspection ConstantConditions @Nonnull String className = osList.getTargetTable().getClassName(); @@ -358,15 +361,54 @@ public RealmList getList(String fieldName) { } /** - * Returns the {@link RealmList} of values being linked from the given field. + * Returns the {@link RealmList} containing only primitive values. + * + *

+ * If the list contains references to other Realm objects, use {@link #getList(String)} instead. * * @param fieldName the name of the field. + * @param elementType the type of elements in the list. Only primitive types are supported. * @return the {@link RealmList} data for this field. - * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain a list of values. + * @throws IllegalArgumentException if field name doesn't exist or it doesn't contain a list of primitive objects. */ - public RealmList getValueList(String fieldName, Class valueClass) { - // TODO implement this - return null; + public RealmList getList(String fieldName, Class elementType) { + proxyState.getRealm$realm().checkIfValid(); + + if (elementType == null) { + throw new IllegalArgumentException("Non-null 'elementType' required."); + } + long columnIndex = proxyState.getRow$realm().getColumnIndex(fieldName); + RealmFieldType realmType = classToRealmType(elementType); + try { + OsList osList = proxyState.getRow$realm().getValueList(columnIndex, realmType); + return new RealmList<>(elementType, osList, proxyState.getRealm$realm()); + } catch (IllegalArgumentException e) { + checkFieldType(fieldName, columnIndex, realmType); + throw e; + } + } + + private RealmFieldType classToRealmType(Class elementType) { + if (elementType.equals(Integer.class) + || elementType.equals(Long.class) + || elementType.equals(Short.class) + || elementType.equals(Byte.class)) { + return RealmFieldType.INTEGER_LIST; + } else if (elementType.equals(Boolean.class)) { + return RealmFieldType.BOOLEAN_LIST; + } else if (elementType.equals(String.class)) { + return RealmFieldType.STRING_LIST; + } else if (elementType.equals(byte[].class)) { + return RealmFieldType.BINARY_LIST; + } else if (elementType.equals(Date.class)) { + return RealmFieldType.DATE_LIST; + } else if (elementType.equals(Float.class)) { + return RealmFieldType.FLOAT_LIST; + } else if (elementType.equals(Double.class)) { + return RealmFieldType.DOUBLE_LIST; + } else { + throw new IllegalArgumentException("Unsupported element type. Only primitive types supported. Yours was: " + elementType); + } } /** @@ -393,6 +435,15 @@ public boolean isNull(String fieldName) { case DATE: return proxyState.getRow$realm().isNull(columnIndex); case LIST: + case LINKING_OBJECTS: + case INTEGER_LIST: + case BOOLEAN_LIST: + case STRING_LIST: + case BINARY_LIST: + case DATE_LIST: + case FLOAT_LIST: + case DOUBLE_LIST: + // fall through default: return false; } @@ -510,28 +561,7 @@ private void setValue(String fieldName, Object value) { setObject(fieldName, (DynamicRealmObject) value); } else if (valueClass == RealmList.class) { RealmList list = (RealmList) value; - if (list.className == null && list.clazz == null) { - // unmanaged RealmList - long columnIndex = proxyState.getRow$realm().getColumnIndex(fieldName); - final RealmFieldType columnType = proxyState.getRow$realm().getColumnType(columnIndex); - if (columnType == RealmFieldType.LIST) { - //noinspection unchecked - for (Object element : list) { - if (!(element instanceof RealmModel)) { - throw new IllegalArgumentException("All elements in the list must be an instance of RealmModel."); - } - } - //noinspection unchecked - setList(fieldName, (RealmList) list); - } else { - setValueList(fieldName, list); - } - } else if (list.className != null || RealmModel.class.isAssignableFrom(list.clazz)) { - //noinspection unchecked - setList(fieldName, (RealmList) list); - } else { - setValueList(fieldName, list); - } + setList(fieldName, list); } else { throw new IllegalArgumentException("Value is of an type not supported: " + value.getClass()); } @@ -727,21 +757,44 @@ public void setObject(String fieldName, @Nullable DynamicRealmObject value) { * Sets the reference to a {@link RealmList} on the given field. * * @param fieldName field name. - * @param list list of references. - * @throws IllegalArgumentException if field name doesn't exist, it is not a list field, the type - * of the object represented by the DynamicRealmObject doesn't match or any element in the list belongs to a - * different Realm. + * @param list list of objects. Must either be primitive types or Realm objects. + * @throws IllegalArgumentException if field name doesn't exist, it is not a list field, the objects in the + * list doesn't match the expected type or any Realm object in the list belongs to a different Realm. */ - public void setList(String fieldName, RealmList list) { + public void setList(String fieldName, RealmList list) { proxyState.getRealm$realm().checkIfValid(); //noinspection ConstantConditions if (list == null) { - throw new IllegalArgumentException("Null values not allowed for lists"); + throw new IllegalArgumentException("Non-null 'list' required"); } + // Find type of list in Realm long columnIndex = proxyState.getRow$realm().getColumnIndex(fieldName); - OsList osList = proxyState.getRow$realm().getList(columnIndex); + final RealmFieldType columnType = proxyState.getRow$realm().getColumnType(columnIndex); + + switch (columnType) { + case LIST: + //noinspection unchecked + setModelList(fieldName, (RealmList) list); + break; + case INTEGER_LIST: + case BOOLEAN_LIST: + case STRING_LIST: + case BINARY_LIST: + case DATE_LIST: + case FLOAT_LIST: + case DOUBLE_LIST: + setValueList(fieldName, list, columnType); + break; + default: + throw new IllegalArgumentException(String.format("Field '%s' is not a list but a %s", fieldName, columnType)); + } + } + + private void setModelList(String fieldName, RealmList list) { + long columnIndex = proxyState.getRow$realm().getColumnIndex(fieldName); + OsList osList = proxyState.getRow$realm().getModelList(columnIndex); Table linkTargetTable = osList.getTargetTable(); //noinspection ConstantConditions @Nonnull @@ -788,17 +841,72 @@ public void setList(String fieldName, RealmList list) { } } - /** - * Sets the reference to a {@link RealmList} on the given field. - * - * @param fieldName field name. - * @param list list of references. - * @throws IllegalArgumentException if field name doesn't exist, it is not a list field, the type - * of the object represented by the DynamicRealmObject doesn't match or any element in the list belongs to a - * different Realm. - */ - public void setValueList(String fieldName, RealmList list) { - // TODO implement this + @SuppressWarnings("unchecked") + private void setValueList(String fieldName, RealmList list, RealmFieldType elementType) { + long columnIndex = proxyState.getRow$realm().getColumnIndex(fieldName); + OsList osList = proxyState.getRow$realm().getValueList(columnIndex, elementType); + + Class elementClass; + switch(elementType) { + case INTEGER_LIST: elementClass = (Class) Long.class; break; + case BOOLEAN_LIST: elementClass = (Class) Boolean.class; break; + case STRING_LIST: elementClass = (Class) String.class; break; + case BINARY_LIST: elementClass = (Class) byte[].class; break; + case DATE_LIST: elementClass = (Class) Date.class; break; + case FLOAT_LIST: elementClass = (Class) Float.class; break; + case DOUBLE_LIST: elementClass = (Class) Double.class; break; + default: + throw new IllegalArgumentException("Unsupported type: " + elementType); + } + final ManagedListOperator operator = getOperator(proxyState.getRealm$realm(), osList, elementType, elementClass); + + if (list.isManaged() && osList.size() == list.size()) { + // There is a chance that the source list and the target list are the same list in the same object. + // In this case, we can't use removeAll(). + final int size = list.size(); + final Iterator iterator = list.iterator(); + for (int i = 0; i < size; i++) { + @Nullable + final Object value = iterator.next(); + operator.set(i, value); + } + } else { + osList.removeAll(); + for (Object value : list) { + operator.append(value); + } + } + } + + private ManagedListOperator getOperator(BaseRealm realm, OsList osList, RealmFieldType valueListType, Class valueClass) { + if (valueListType == RealmFieldType.STRING_LIST) { + //noinspection unchecked + return (ManagedListOperator) new StringListOperator(realm, osList, (Class) valueClass); + } + if (valueListType == RealmFieldType.INTEGER_LIST) { + return new LongListOperator<>(realm, osList, valueClass); + } + if (valueListType == RealmFieldType.BOOLEAN_LIST) { + //noinspection unchecked + return (ManagedListOperator) new BooleanListOperator(realm, osList, (Class) valueClass); + } + if (valueListType == RealmFieldType.BINARY_LIST) { + //noinspection unchecked + return (ManagedListOperator) new BinaryListOperator(realm, osList, (Class) valueClass); + } + if (valueListType == RealmFieldType.DOUBLE_LIST) { + //noinspection unchecked + return (ManagedListOperator) new DoubleListOperator(realm, osList, (Class) valueClass); + } + if (valueListType == RealmFieldType.FLOAT_LIST) { + //noinspection unchecked + return (ManagedListOperator) new FloatListOperator(realm, osList, (Class) valueClass); + } + if (valueListType == RealmFieldType.DATE_LIST) { + //noinspection unchecked + return (ManagedListOperator) new DateListOperator(realm, osList, (Class) valueClass); + } + throw new IllegalArgumentException("Unexpected list type: " + valueListType.name()); } /** @@ -964,7 +1072,28 @@ public String toString() { break; case LIST: String targetClassName = proxyState.getRow$realm().getTable().getLinkTarget(columnIndex).getClassName(); - sb.append(String.format(Locale.US, "RealmList<%s>[%s]", targetClassName, proxyState.getRow$realm().getList(columnIndex).size())); + sb.append(String.format(Locale.US, "RealmList<%s>[%s]", targetClassName, proxyState.getRow$realm().getModelList(columnIndex).size())); + break; + case INTEGER_LIST: + sb.append(String.format(Locale.US, "RealmList[%s]", proxyState.getRow$realm().getValueList(columnIndex, type).size())); + break; + case BOOLEAN_LIST: + sb.append(String.format(Locale.US, "RealmList[%s]", proxyState.getRow$realm().getValueList(columnIndex, type).size())); + break; + case STRING_LIST: + sb.append(String.format(Locale.US, "RealmList[%s]", proxyState.getRow$realm().getValueList(columnIndex, type).size())); + break; + case BINARY_LIST: + sb.append(String.format(Locale.US, "RealmList[%s]", proxyState.getRow$realm().getValueList(columnIndex, type).size())); + break; + case DATE_LIST: + sb.append(String.format(Locale.US, "RealmList[%s]", proxyState.getRow$realm().getValueList(columnIndex, type).size())); + break; + case FLOAT_LIST: + sb.append(String.format(Locale.US, "RealmList[%s]", proxyState.getRow$realm().getValueList(columnIndex, type).size())); + break; + case DOUBLE_LIST: + sb.append(String.format(Locale.US, "RealmList[%s]", proxyState.getRow$realm().getValueList(columnIndex, type).size())); break; default: sb.append("?"); diff --git a/realm/realm-library/src/main/java/io/realm/RealmList.java b/realm/realm-library/src/main/java/io/realm/RealmList.java index 7bcbe78c35..b13841e276 100644 --- a/realm/realm-library/src/main/java/io/realm/RealmList.java +++ b/realm/realm-library/src/main/java/io/realm/RealmList.java @@ -70,7 +70,7 @@ public class RealmList extends AbstractList implements OrderedRealmCollect protected String className; // Always null if RealmList is unmanaged, always non-null if managed. - private final ManagedListOperator osListOperator; + final ManagedListOperator osListOperator; final protected BaseRealm realm; private List unmanagedList; // Used for listeners on RealmList diff --git a/realm/realm-library/src/main/java/io/realm/internal/CheckedRow.java b/realm/realm-library/src/main/java/io/realm/internal/CheckedRow.java index f3a3e1f97b..115130670b 100644 --- a/realm/realm-library/src/main/java/io/realm/internal/CheckedRow.java +++ b/realm/realm-library/src/main/java/io/realm/internal/CheckedRow.java @@ -97,17 +97,6 @@ public void setNull(long columnIndex) { } } - @Override - public OsList getList(long columnIndex) { - RealmFieldType fieldType = getTable().getColumnType(columnIndex); - if (fieldType != RealmFieldType.LIST) { - throw new IllegalArgumentException( - String.format(Locale.US, "Field '%s' is not a 'RealmList'.", - getTable().getColumnName(columnIndex))); - } - return super.getList(columnIndex); - } - @Override public OsList getModelList(long columnIndex) { RealmFieldType fieldType = getTable().getColumnType(columnIndex); diff --git a/realm/realm-library/src/main/java/io/realm/internal/InvalidRow.java b/realm/realm-library/src/main/java/io/realm/internal/InvalidRow.java index 79510c7e08..42f160d1d9 100644 --- a/realm/realm-library/src/main/java/io/realm/internal/InvalidRow.java +++ b/realm/realm-library/src/main/java/io/realm/internal/InvalidRow.java @@ -104,11 +104,6 @@ public boolean isNullLink(long columnIndex) { throw getStubException(); } - @Override - public OsList getList(long columnIndex) { - throw getStubException(); - } - @Override public OsList getModelList(long columnIndex) { throw getStubException(); diff --git a/realm/realm-library/src/main/java/io/realm/internal/PendingRow.java b/realm/realm-library/src/main/java/io/realm/internal/PendingRow.java index 88ace3a27b..638fc3d5f8 100644 --- a/realm/realm-library/src/main/java/io/realm/internal/PendingRow.java +++ b/realm/realm-library/src/main/java/io/realm/internal/PendingRow.java @@ -133,11 +133,6 @@ public boolean isNullLink(long columnIndex) { throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE); } - @Override - public OsList getList(long columnIndex) { - throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE); - } - @Override public OsList getModelList(long columnIndex) { throw new IllegalStateException(QUERY_NOT_RETURNED_MESSAGE); diff --git a/realm/realm-library/src/main/java/io/realm/internal/Row.java b/realm/realm-library/src/main/java/io/realm/internal/Row.java index f1a556f057..681d818999 100644 --- a/realm/realm-library/src/main/java/io/realm/internal/Row.java +++ b/realm/realm-library/src/main/java/io/realm/internal/Row.java @@ -81,9 +81,6 @@ public interface Row { boolean isNullLink(long columnIndex); - // FIXME remove this in DynamicRealm PR - OsList getList(long columnIndex); - OsList getModelList(long columnIndex); OsList getValueList(long columnIndex, RealmFieldType fieldType); diff --git a/realm/realm-library/src/main/java/io/realm/internal/UncheckedRow.java b/realm/realm-library/src/main/java/io/realm/internal/UncheckedRow.java index 5c98952c7d..c7e035b89c 100644 --- a/realm/realm-library/src/main/java/io/realm/internal/UncheckedRow.java +++ b/realm/realm-library/src/main/java/io/realm/internal/UncheckedRow.java @@ -172,11 +172,6 @@ public boolean isNullLink(long columnIndex) { return nativeIsNullLink(nativePtr, columnIndex); } - @Override - public OsList getList(long columnIndex) { - return new OsList(this, columnIndex); - } - @Override public OsList getModelList(long columnIndex) { return new OsList(this, columnIndex);