TRINIDAD-2480
Register Table's InternalState as RowKeyChangeListener to CollectionModel
thanks to Jing
diff --git a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java
index f134d5a..c4c90ca 100644
--- a/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java
+++ b/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXCollection.java
@@ -54,6 +54,8 @@
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
import org.apache.myfaces.trinidad.model.CollectionModel;
import org.apache.myfaces.trinidad.model.LocalRowKeyIndex;
+import org.apache.myfaces.trinidad.model.RowKeyChangeEvent;
+import org.apache.myfaces.trinidad.model.RowKeyChangeListener;
import org.apache.myfaces.trinidad.model.SortCriterion;
import org.apache.myfaces.trinidad.render.ClientRowKeyManager;
import org.apache.myfaces.trinidad.render.ClientRowKeyManagerFactory;
@@ -491,6 +493,7 @@
// It is bad if the rowKey changes after _restoreStampState() and
// before _saveStampState(). Therefore, we cache it:
iState._currentRowKey = getCollectionModel().getRowKey();
+ iState._model.addRowKeyChangeListener(iState);
}
return iState._currentRowKey;
@@ -952,6 +955,9 @@
InternalState iState = _getInternalState(true);
// mark the cached rowKey as invalid:
iState._currentRowKey = _NULL;
+ // we don't have cached rowkey, thus remove rowkeychangelistener
+ if (iState._model != null)
+ iState._model.removeRowKeyChangeListener(iState);
}
/**
@@ -1963,9 +1969,27 @@
Object value = getValue();
if (iState._value != value)
{
+ CollectionModel oldModel = iState._model;
iState._value = value;
iState._model = createCollectionModel(iState._model, value);
postCreateCollectionModel(iState._model);
+
+ // if the underlying model is changed, we need to remove
+ // the listener from the old model. And if we still have cached
+ // rowkey, we need to add the listener back to the new model.
+
+ if (oldModel != iState._model)
+ {
+ if (oldModel != null)
+ {
+ oldModel.removeRowKeyChangeListener(iState);
+ }
+
+ if (iState._currentRowKey != _NULL)
+ {
+ iState._model.addRowKeyChangeListener(iState);
+ }
+ }
}
}
@@ -2323,7 +2347,12 @@
if (iState != null)
{
iState._value = null;
- iState._model= null;
+
+ if (iState._model != null)
+ {
+ iState._model.removeRowKeyChangeListener(iState);
+ iState._model = null;
+ }
}
}
@@ -2405,7 +2434,7 @@
// easy to quickly suck out or restore its internal state,
// when this component is itself used as a stamp inside some other
// stamping container, eg: nested tables.
- private static final class InternalState implements Serializable
+ private static final class InternalState implements RowKeyChangeListener, Serializable
{
private transient boolean _hasEvent = false;
private transient Object _prevVarValue = _NULL;
@@ -2433,6 +2462,35 @@
// changes in the middle, we'll still be able to find the right stamp state.
private Map<String, String> _idToIndexMap = null;
+ public void onRowKeyChange(RowKeyChangeEvent rowKeyChangeEvent)
+ {
+ Object newKey = rowKeyChangeEvent.getNewRowKey();
+ Object oldKey = rowKeyChangeEvent.getOldRowKey();
+
+ if (newKey != null && oldKey != null && !newKey.equals(oldKey))
+ {
+ // first replace the cached row key
+ if (oldKey.equals(_currentRowKey))
+ _currentRowKey = newKey;
+
+ // then update stamp state for the affected entries.
+ if (_stampState == null || _idToIndexMap == null)
+ return;
+
+ int stampCompCount = _idToIndexMap.size();
+
+ for (int index = 0; index < stampCompCount; index++)
+ {
+ String stampId = String.valueOf(index);
+ Object state = _stampState.get(oldKey, stampId);
+ if (state == null)
+ continue;
+ _stampState.put(oldKey, stampId, null);
+ _stampState.put(newKey, stampId, state);
+ }
+ }
+ }
+
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException
{