Did entertain myself with the idea and tried to implement it. Attached is
a roughly tested patch.
I changed the name of IPrimaryKeyProvider to IPrimaryKeyDataProvider.
I also did replace the Map in DataView.onRender() with an array.
Christian
On Wed, 10 Aug 2005 14:35:45 -0700, Igor Vaynberg <[EMAIL PROTECTED]>
wrote:
Alrite, without spending too much more time on this, entartain this idea:
Move primarykey to IPrimaryKeyProvider { String primaryKey() }
The dataview can do an instanceof check on the impl of IDataProvider, if
it
implements iprimarykeyprovider use that otherwise use a generic counter.
-Igor
Index: DataView.java
===================================================================
RCS file:
/cvsroot/wicket-stuff/wicket-contrib-dataview/src/wicket/contrib/dataview/DataView.java,v
retrieving revision 1.8
diff -u -r1.8 DataView.java
--- DataView.java 10 Aug 2005 04:55:09 -0000 1.8
+++ DataView.java 11 Aug 2005 00:51:48 -0000
@@ -57,6 +57,11 @@
private int cachedItemCount = -1;
/**
+ * A counter which will be used to generate generic ids for DataItem
+ */
+ private long _idGenerationCounter = 0; //TODO: check if this holds
enough numbers for unchecked upcount.
+
+ /**
* @see wicket.Component#Component(String)
*/
public DataView(final String id)
@@ -208,9 +213,74 @@
/**
* @see wicket.MarkupContainer#internalOnBeginRequest()
*/
- protected void internalOnBeginRequest()
- {
+ protected void internalOnBeginRequest(){
final IDataProvider dataProvider = getDataProvider();
+ if (dataProvider instanceof IPrimaryKeyDataProvider) {
+ IPrimaryKeyDataProvider pkp =
(IPrimaryKeyDataProvider)dataProvider;
+ internalOnBeginRequestPrimaryKey(pkp);
+ }else{
+ internalOnBeginRequestIModel(dataProvider);
+ }
+ }
+
+ private void internalOnBeginRequestIModel(IDataProvider dataProvider)
+ {
+ // Get number of items to be displayed
+ final int size = getViewSize();
+
+ if (size > 0)
+ {
+ Iterator it = null;
+
+ Map existingDataItems = new HashMap(size());
+ it = iterator();
+ while (it.hasNext())
+ {
+ final DataItem child = (DataItem)it.next();
+ existingDataItems.put(child.getModel(),child);
+ }
+
+ it = dataProvider.iterator(firstIndex, size);
+
+ // render all items not already present
+ int index = 0;
+ while (it.hasNext()&&index<size)
+ {
+ final Object object = it.next();
+ final String id =
"DataViewUniqueName"+_idGenerationCounter++;
+ final IModel newModel =
dataProvider.model(object);
+
+ DataItem item =
(DataItem)existingDataItems.get(newModel);
+ if (item == null)
+ {
+ item = newItem(id, index, newModel);
+ add(item);
+ populateItem(item);
+ }
+ else
+ {
+ item.setIndex(index);
+ existingDataItems.remove(newModel);
+ }
+ index++;
+ }
+
+ // remove dataitems no longer present in the view
+ it = existingDataItems.values().iterator();
+ while (it.hasNext())
+ {
+ DataItem item = (DataItem)it.next();
+ remove(item.getId());
+ }
+ }
+ else
+ {
+ removeAll();
+ }
+ }
+
+ private void internalOnBeginRequestPrimaryKey(final
IPrimaryKeyDataProvider dataProvider)
+ {
// Get number of items to be displayed
final int size = getViewSize();
@@ -290,23 +360,31 @@
// maybe keep a map like this always updated as a field? what
about
// versioning?
- Map itemsByIndex = new HashMap();
+ // just a proposal: (Christian)
+ final int size = getViewSize();
+ DataItem[] itemsByIndex = new DataItem[size];
Iterator it = iterator();
while (it.hasNext())
{
final DataItem item = (DataItem)it.next();
- itemsByIndex.put(new Integer(item.getIndex()), item);
+ int index = item.getIndex();
+ try{
+ itemsByIndex[index] = item;
+ }catch(IndexOutOfBoundsException e){
+ throw new WicketRuntimeException("DataItem with
index [" + index
+ + "] is out of viewSize [" +
size + "]");
+
+ }
}
// Get number of items to be displayed
- final int size = getViewSize();
if (size > 0)
{
// Loop through the markup in this container for each
item
for (int i = 0; i < size; i++)
{
// If this component does not already exist,
populate it
- DataItem item = (DataItem)itemsByIndex.get(new
Integer(i));
+ DataItem item = itemsByIndex[i];
if (item == null)
{
Index: IDataProvider.java
===================================================================
RCS file:
/cvsroot/wicket-stuff/wicket-contrib-dataview/src/wicket/contrib/dataview/IDataProvider.java,v
retrieving revision 1.3
diff -u -r1.3 IDataProvider.java
--- IDataProvider.java 2 Aug 2005 16:48:26 -0000 1.3
+++ IDataProvider.java 11 Aug 2005 00:51:48 -0000
@@ -63,12 +63,4 @@
*/
IModel model(Object object);
- /**
- * return stringized primary key for the current object
- *
- * @param object
- * object whose primary key will be returned
- * @return object's primary key
- */
- String primaryKey(Object object);
}
Index: IPrimaryKeyDataProvider.java
===================================================================
RCS file: IPrimaryKeyDataProvider.java
diff -N IPrimaryKeyDataProvider.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ IPrimaryKeyDataProvider.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,20 @@
+package wicket.contrib.dataview;
+
+/**
+ * An IDataProvider which also provides a primaryKey for optimized itemremoval
based on
+ * the primary key.
+ * @author Igor Vaynberg ( ivaynberg )
+ *
+ */
+public interface IPrimaryKeyDataProvider extends IDataProvider
+{
+ /**
+ * return stringized primary key for the current object
+ *
+ * @param object
+ * object whose primary key will be returned
+ * @return object's primary key
+ */
+ String primaryKey(Object object);
+
+}