From 2e1b9da46e95a29a926a8e67443c8254027ef29e Mon Sep 17 00:00:00 2001 From: Makoto Yamazaki Date: Thu, 17 Nov 2016 19:39:31 +0900 Subject: [PATCH 1/2] initial fix for #3809 --- .../processor/RealmProxyClassGenerator.java | 25 +++++- .../io/realm/AllTypesRealmProxy.java | 9 ++ .../src/main/java/io/realm/RealmList.java | 89 +++++++++++++++---- 3 files changed, 104 insertions(+), 19 deletions(-) diff --git a/realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyClassGenerator.java b/realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyClassGenerator.java index eb99fbeb6e..78553ee91b 100644 --- a/realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyClassGenerator.java +++ b/realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyClassGenerator.java @@ -229,8 +229,23 @@ private void emitConstructor(JavaWriter writer) throws IOException { // FooRealmProxy(ColumnInfo) writer.beginConstructor(EnumSet.noneOf(Modifier.class)); writer.beginControlFlow("if (proxyState == null)") - .emitStatement("injectObjectContext()") - .endControlFlow(); + .emitStatement("injectObjectContext()"); + boolean isFirstRealmListField = true; + for (VariableElement field : metadata.getFields()) { + if (!Utils.isRealmList(field)) { + continue; + } + if (isFirstRealmListField) { + writer.nextControlFlow("else"); + isFirstRealmListField = false; + } + final String realmListCacheFieldName = field.getSimpleName().toString() + "RealmList"; + writer.beginControlFlow("if (%1$s != null)", realmListCacheFieldName); + writer.emitStatement("%1$s.setIgnoreModification(false)", realmListCacheFieldName); + writer.endControlFlow(); + } + writer.endControlFlow(); + writer.emitStatement("proxyState.setConstructionFinished()"); writer.endConstructor(); writer.emitEmptyLine(); @@ -404,6 +419,12 @@ public void emit(JavaWriter writer) throws IOException { writer.emitStatement("LinkView linkView = proxyState.getRow$realm().getLinkList(%s)", fieldIndexVariableReference(field)); writer.emitStatement(fieldName + "RealmList = new RealmList<%s>(%s.class, linkView, proxyState.getRealm$realm())", genericType, genericType); + writer.beginControlFlow("if (proxyState.isUnderConstruction())"); + writer.beginControlFlow("if (!proxyState.getAcceptDefaultValue$realm() || proxyState.getExcludeFields$realm().contains(\"%1$s\"))", + fieldName); + writer.emitStatement("%1$sRealmList.setIgnoreModification(true)", fieldName); + writer.endControlFlow(); + writer.endControlFlow(); writer.emitStatement("return " + fieldName + "RealmList"); writer.endControlFlow(); diff --git a/realm/realm-annotations-processor/src/test/resources/io/realm/AllTypesRealmProxy.java b/realm/realm-annotations-processor/src/test/resources/io/realm/AllTypesRealmProxy.java index 7bf9205056..ff127ae456 100644 --- a/realm/realm-annotations-processor/src/test/resources/io/realm/AllTypesRealmProxy.java +++ b/realm/realm-annotations-processor/src/test/resources/io/realm/AllTypesRealmProxy.java @@ -112,6 +112,10 @@ public final AllTypesColumnInfo clone() { AllTypesRealmProxy() { if (proxyState == null) { injectObjectContext(); + } else { + if (columnRealmListRealmList != null) { + columnRealmListRealmList.setIgnoreModification(false); + } } proxyState.setConstructionFinished(); } @@ -416,6 +420,11 @@ private void injectObjectContext() { } else { LinkView linkView = proxyState.getRow$realm().getLinkList(columnInfo.columnRealmListIndex); columnRealmListRealmList = new RealmList(some.test.AllTypes.class, linkView, proxyState.getRealm$realm()); + if (proxyState.isUnderConstruction()) { + if (!proxyState.getAcceptDefaultValue$realm() || proxyState.getExcludeFields$realm().contains("columnRealmList")) { + columnRealmListRealmList.setIgnoreModification(true); + } + } return columnRealmListRealmList; } } 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 d909155433..bcfa54eeca 100644 --- a/realm/realm-library/src/main/java/io/realm/RealmList.java +++ b/realm/realm-library/src/main/java/io/realm/RealmList.java @@ -61,6 +61,7 @@ public class RealmList extends AbstractList implements protected LinkView view; protected BaseRealm realm; private List unmanagedList; + private boolean ignoreModification; /** * Creates a RealmList in unmanaged mode, where the elements are not controlled by a Realm. @@ -113,6 +114,10 @@ public RealmList(E... objects) { this.className = className; } + void setIgnoreModification(boolean ignoreModification) { + this.ignoreModification = ignoreModification; + } + /** * {@inheritDoc} */ @@ -160,6 +165,10 @@ private boolean isAttached() { @Override public void add(int location, E object) { checkValidObject(object); + if (ignoreModification) { + return; + } + if (managedMode) { checkValidView(); if (location < 0 || location > size()) { @@ -192,6 +201,9 @@ public void add(int location, E object) { @Override public boolean add(E object) { checkValidObject(object); + if (ignoreModification) { + return true; + } if (managedMode) { checkValidView(); RealmObjectProxy proxy = (RealmObjectProxy) copyToRealmIfNeeded(object); @@ -227,12 +239,18 @@ public E set(int location, E object) { E oldObject; if (managedMode) { checkValidView(); - RealmObjectProxy proxy = (RealmObjectProxy) copyToRealmIfNeeded(object); oldObject = get(location); - view.set(location, proxy.realmGet$proxyState().getRow$realm().getIndex()); + if (!ignoreModification) { + RealmObjectProxy proxy = (RealmObjectProxy) copyToRealmIfNeeded(object); + view.set(location, proxy.realmGet$proxyState().getRow$realm().getIndex()); + } return oldObject; } else { - oldObject = unmanagedList.set(location, object); + if (ignoreModification) { + oldObject = unmanagedList.get(location); + } else { + oldObject = unmanagedList.set(location, object); + } } return oldObject; } @@ -295,15 +313,19 @@ private E copyToRealmIfNeeded(E object) { public void move(int oldPos, int newPos) { if (managedMode) { checkValidView(); - view.move(oldPos, newPos); + if (!ignoreModification) { + view.move(oldPos, newPos); + } } else { checkIndex(oldPos); checkIndex(newPos); - E object = unmanagedList.remove(oldPos); - if (newPos > oldPos) { - unmanagedList.add(newPos - 1, object); - } else { - unmanagedList.add(newPos, object); + if (!ignoreModification) { + E object = unmanagedList.remove(oldPos); + if (newPos > oldPos) { + unmanagedList.add(newPos - 1, object); + } else { + unmanagedList.add(newPos, object); + } } } } @@ -320,11 +342,16 @@ public void move(int oldPos, int newPos) { public void clear() { if (managedMode) { checkValidView(); - view.clear(); + if (!ignoreModification) { + view.clear(); + modCount++; + } } else { - unmanagedList.clear(); + if (!ignoreModification) { + unmanagedList.clear(); + modCount++; + } } - modCount++; } /** @@ -341,11 +368,18 @@ public E remove(int location) { if (managedMode) { checkValidView(); removedItem = get(location); - view.remove(location); + if (!ignoreModification) { + view.remove(location); + modCount++; + } } else { - removedItem = unmanagedList.remove(location); + if (ignoreModification) { + removedItem = unmanagedList.get(location); + } else { + removedItem = unmanagedList.remove(location); + modCount++; + } } - modCount++; return removedItem; } @@ -368,6 +402,9 @@ public E remove(int location) { */ @Override public boolean remove(Object object) { + if (ignoreModification) { + return false; + } if (managedMode && !realm.isInTransaction()) { throw new IllegalStateException(REMOVE_OUTSIDE_TRANSACTION_ERROR); } @@ -392,6 +429,9 @@ public boolean remove(Object object) { */ @Override public boolean removeAll(Collection collection) { + if (ignoreModification) { + return false; + } if (managedMode && !realm.isInTransaction()) { throw new IllegalStateException(REMOVE_OUTSIDE_TRANSACTION_ERROR); } @@ -403,10 +443,10 @@ public boolean removeAll(Collection collection) { */ @Override public boolean deleteFirstFromRealm() { + // no need to check ignoreModification since deleteFromRealm does. if (managedMode) { if (size() > 0) { deleteFromRealm(0); - modCount++; return true; } else { return false; @@ -421,10 +461,10 @@ public boolean deleteFirstFromRealm() { */ @Override public boolean deleteLastFromRealm() { + // no need to check ignoreModification since deleteFromRealm does. if (managedMode) { if (size() > 0) { deleteFromRealm(size() - 1); - modCount++; return true; } else { return false; @@ -562,6 +602,9 @@ public RealmResults sort(String[] fieldNames, Sort[] sortOrders) { public void deleteFromRealm(int location) { if (managedMode) { checkValidView(); + if (ignoreModification) { + return; + } view.removeTargetRow(location); modCount++; } else { @@ -681,6 +724,9 @@ public Date minDate(String fieldName) { public boolean deleteAllFromRealm() { if (managedMode) { checkValidView(); + if (ignoreModification) { + return false; + } if (size() > 0) { view.removeAllTargetRows(); modCount++; @@ -875,6 +921,9 @@ public void remove() { throw new IllegalStateException("Cannot call remove() twice. Must call next() in between."); } checkConcurrentModification(); + if (ignoreModification) { + return; + } try { RealmList.this.remove(lastRet); @@ -958,6 +1007,9 @@ public void set(E e) { } checkConcurrentModification(); + if (ignoreModification) { + return; + } try { RealmList.this.set(lastRet, e); expectedModCount = modCount; @@ -975,6 +1027,9 @@ public void set(E e) { public void add(E e) { realm.checkIfValid(); checkConcurrentModification(); + if (ignoreModification) { + return; + } try { int i = cursor; RealmList.this.add(i, e); From 73f9223dcdc6a801740f2bf02ff35c37aecb4026 Mon Sep 17 00:00:00 2001 From: Makoto Yamazaki Date: Tue, 21 Feb 2017 20:45:39 +0900 Subject: [PATCH 2/2] Revert "initial fix for #3809" This reverts commit 2e1b9da46e95a29a926a8e67443c8254027ef29e. --- .../processor/RealmProxyClassGenerator.java | 25 +----- .../io/realm/AllTypesRealmProxy.java | 9 -- .../src/main/java/io/realm/RealmList.java | 89 ++++--------------- 3 files changed, 19 insertions(+), 104 deletions(-) diff --git a/realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyClassGenerator.java b/realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyClassGenerator.java index 78553ee91b..eb99fbeb6e 100644 --- a/realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyClassGenerator.java +++ b/realm/realm-annotations-processor/src/main/java/io/realm/processor/RealmProxyClassGenerator.java @@ -229,23 +229,8 @@ private void emitConstructor(JavaWriter writer) throws IOException { // FooRealmProxy(ColumnInfo) writer.beginConstructor(EnumSet.noneOf(Modifier.class)); writer.beginControlFlow("if (proxyState == null)") - .emitStatement("injectObjectContext()"); - boolean isFirstRealmListField = true; - for (VariableElement field : metadata.getFields()) { - if (!Utils.isRealmList(field)) { - continue; - } - if (isFirstRealmListField) { - writer.nextControlFlow("else"); - isFirstRealmListField = false; - } - final String realmListCacheFieldName = field.getSimpleName().toString() + "RealmList"; - writer.beginControlFlow("if (%1$s != null)", realmListCacheFieldName); - writer.emitStatement("%1$s.setIgnoreModification(false)", realmListCacheFieldName); - writer.endControlFlow(); - } - writer.endControlFlow(); - + .emitStatement("injectObjectContext()") + .endControlFlow(); writer.emitStatement("proxyState.setConstructionFinished()"); writer.endConstructor(); writer.emitEmptyLine(); @@ -419,12 +404,6 @@ public void emit(JavaWriter writer) throws IOException { writer.emitStatement("LinkView linkView = proxyState.getRow$realm().getLinkList(%s)", fieldIndexVariableReference(field)); writer.emitStatement(fieldName + "RealmList = new RealmList<%s>(%s.class, linkView, proxyState.getRealm$realm())", genericType, genericType); - writer.beginControlFlow("if (proxyState.isUnderConstruction())"); - writer.beginControlFlow("if (!proxyState.getAcceptDefaultValue$realm() || proxyState.getExcludeFields$realm().contains(\"%1$s\"))", - fieldName); - writer.emitStatement("%1$sRealmList.setIgnoreModification(true)", fieldName); - writer.endControlFlow(); - writer.endControlFlow(); writer.emitStatement("return " + fieldName + "RealmList"); writer.endControlFlow(); diff --git a/realm/realm-annotations-processor/src/test/resources/io/realm/AllTypesRealmProxy.java b/realm/realm-annotations-processor/src/test/resources/io/realm/AllTypesRealmProxy.java index ff127ae456..7bf9205056 100644 --- a/realm/realm-annotations-processor/src/test/resources/io/realm/AllTypesRealmProxy.java +++ b/realm/realm-annotations-processor/src/test/resources/io/realm/AllTypesRealmProxy.java @@ -112,10 +112,6 @@ public final AllTypesColumnInfo clone() { AllTypesRealmProxy() { if (proxyState == null) { injectObjectContext(); - } else { - if (columnRealmListRealmList != null) { - columnRealmListRealmList.setIgnoreModification(false); - } } proxyState.setConstructionFinished(); } @@ -420,11 +416,6 @@ private void injectObjectContext() { } else { LinkView linkView = proxyState.getRow$realm().getLinkList(columnInfo.columnRealmListIndex); columnRealmListRealmList = new RealmList(some.test.AllTypes.class, linkView, proxyState.getRealm$realm()); - if (proxyState.isUnderConstruction()) { - if (!proxyState.getAcceptDefaultValue$realm() || proxyState.getExcludeFields$realm().contains("columnRealmList")) { - columnRealmListRealmList.setIgnoreModification(true); - } - } return columnRealmListRealmList; } } 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 bcfa54eeca..d909155433 100644 --- a/realm/realm-library/src/main/java/io/realm/RealmList.java +++ b/realm/realm-library/src/main/java/io/realm/RealmList.java @@ -61,7 +61,6 @@ public class RealmList extends AbstractList implements protected LinkView view; protected BaseRealm realm; private List unmanagedList; - private boolean ignoreModification; /** * Creates a RealmList in unmanaged mode, where the elements are not controlled by a Realm. @@ -114,10 +113,6 @@ public RealmList(E... objects) { this.className = className; } - void setIgnoreModification(boolean ignoreModification) { - this.ignoreModification = ignoreModification; - } - /** * {@inheritDoc} */ @@ -165,10 +160,6 @@ private boolean isAttached() { @Override public void add(int location, E object) { checkValidObject(object); - if (ignoreModification) { - return; - } - if (managedMode) { checkValidView(); if (location < 0 || location > size()) { @@ -201,9 +192,6 @@ public void add(int location, E object) { @Override public boolean add(E object) { checkValidObject(object); - if (ignoreModification) { - return true; - } if (managedMode) { checkValidView(); RealmObjectProxy proxy = (RealmObjectProxy) copyToRealmIfNeeded(object); @@ -239,18 +227,12 @@ public E set(int location, E object) { E oldObject; if (managedMode) { checkValidView(); + RealmObjectProxy proxy = (RealmObjectProxy) copyToRealmIfNeeded(object); oldObject = get(location); - if (!ignoreModification) { - RealmObjectProxy proxy = (RealmObjectProxy) copyToRealmIfNeeded(object); - view.set(location, proxy.realmGet$proxyState().getRow$realm().getIndex()); - } + view.set(location, proxy.realmGet$proxyState().getRow$realm().getIndex()); return oldObject; } else { - if (ignoreModification) { - oldObject = unmanagedList.get(location); - } else { - oldObject = unmanagedList.set(location, object); - } + oldObject = unmanagedList.set(location, object); } return oldObject; } @@ -313,19 +295,15 @@ private E copyToRealmIfNeeded(E object) { public void move(int oldPos, int newPos) { if (managedMode) { checkValidView(); - if (!ignoreModification) { - view.move(oldPos, newPos); - } + view.move(oldPos, newPos); } else { checkIndex(oldPos); checkIndex(newPos); - if (!ignoreModification) { - E object = unmanagedList.remove(oldPos); - if (newPos > oldPos) { - unmanagedList.add(newPos - 1, object); - } else { - unmanagedList.add(newPos, object); - } + E object = unmanagedList.remove(oldPos); + if (newPos > oldPos) { + unmanagedList.add(newPos - 1, object); + } else { + unmanagedList.add(newPos, object); } } } @@ -342,16 +320,11 @@ public void move(int oldPos, int newPos) { public void clear() { if (managedMode) { checkValidView(); - if (!ignoreModification) { - view.clear(); - modCount++; - } + view.clear(); } else { - if (!ignoreModification) { - unmanagedList.clear(); - modCount++; - } + unmanagedList.clear(); } + modCount++; } /** @@ -368,18 +341,11 @@ public E remove(int location) { if (managedMode) { checkValidView(); removedItem = get(location); - if (!ignoreModification) { - view.remove(location); - modCount++; - } + view.remove(location); } else { - if (ignoreModification) { - removedItem = unmanagedList.get(location); - } else { - removedItem = unmanagedList.remove(location); - modCount++; - } + removedItem = unmanagedList.remove(location); } + modCount++; return removedItem; } @@ -402,9 +368,6 @@ public E remove(int location) { */ @Override public boolean remove(Object object) { - if (ignoreModification) { - return false; - } if (managedMode && !realm.isInTransaction()) { throw new IllegalStateException(REMOVE_OUTSIDE_TRANSACTION_ERROR); } @@ -429,9 +392,6 @@ public boolean remove(Object object) { */ @Override public boolean removeAll(Collection collection) { - if (ignoreModification) { - return false; - } if (managedMode && !realm.isInTransaction()) { throw new IllegalStateException(REMOVE_OUTSIDE_TRANSACTION_ERROR); } @@ -443,10 +403,10 @@ public boolean removeAll(Collection collection) { */ @Override public boolean deleteFirstFromRealm() { - // no need to check ignoreModification since deleteFromRealm does. if (managedMode) { if (size() > 0) { deleteFromRealm(0); + modCount++; return true; } else { return false; @@ -461,10 +421,10 @@ public boolean deleteFirstFromRealm() { */ @Override public boolean deleteLastFromRealm() { - // no need to check ignoreModification since deleteFromRealm does. if (managedMode) { if (size() > 0) { deleteFromRealm(size() - 1); + modCount++; return true; } else { return false; @@ -602,9 +562,6 @@ public RealmResults sort(String[] fieldNames, Sort[] sortOrders) { public void deleteFromRealm(int location) { if (managedMode) { checkValidView(); - if (ignoreModification) { - return; - } view.removeTargetRow(location); modCount++; } else { @@ -724,9 +681,6 @@ public Date minDate(String fieldName) { public boolean deleteAllFromRealm() { if (managedMode) { checkValidView(); - if (ignoreModification) { - return false; - } if (size() > 0) { view.removeAllTargetRows(); modCount++; @@ -921,9 +875,6 @@ public void remove() { throw new IllegalStateException("Cannot call remove() twice. Must call next() in between."); } checkConcurrentModification(); - if (ignoreModification) { - return; - } try { RealmList.this.remove(lastRet); @@ -1007,9 +958,6 @@ public void set(E e) { } checkConcurrentModification(); - if (ignoreModification) { - return; - } try { RealmList.this.set(lastRet, e); expectedModCount = modCount; @@ -1027,9 +975,6 @@ public void set(E e) { public void add(E e) { realm.checkIfValid(); checkConcurrentModification(); - if (ignoreModification) { - return; - } try { int i = cursor; RealmList.this.add(i, e);