Author: hlship
Date: Thu Oct 30 17:18:24 2008
New Revision: 709306
URL: http://svn.apache.org/viewvc?rev=709306&view=rev
Log:
TAP54-34: When using a Grid inside a Form, sorting the Grid may cause updates
(when the form is submitted) to be applied to the wrong objects
Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/GridFormEncoderDemo.tml
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/GridFormEncoderDemo.java
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.xdoc
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/GridRows.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Loop.xdoc
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassTransformerImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/util/DefaultPrimaryKeyEncoder.java
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/GridFormDemo.tml
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/GridFormDemo.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/ToDoDatabase.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/ToDoDatabaseImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/log4j.properties
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/CtClassSourceImpl.java
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.java?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.java
Thu Oct 30 17:18:24 2008
@@ -42,8 +42,10 @@
* A Grid may operate inside a [EMAIL PROTECTED]
org.apache.tapestry5.corelib.components.Form}. By overriding the cell renderers
of
* properties, the default output-only behavior can be changed to produce a
complex form with individual control for
* editing properties of each row. This is currently workable but less than
ideal -- if the order of rows provided by
- * the [EMAIL PROTECTED] GridDataSource} changes between render and form
submission, then there's the possibility that data will be
- * applied to the wrong server-side objects.
+ * the [EMAIL PROTECTED] org.apache.tapestry5.grid.GridDataSource} changes
between render and form submission, then there's the
+ * possibility that data will be applied to the wrong server-side objects. In
general, when using Grid and Form
+ * together, you want to provide the Grid with a [EMAIL PROTECTED]
org.apache.tapestry5.PrimaryKeyEncoder} (via the encoder
+ * parameter).
*
* @see org.apache.tapestry5.beaneditor.BeanModel
* @see org.apache.tapestry5.services.BeanModelSource
@@ -204,6 +206,14 @@
private boolean inPlace;
/**
+ * Changes how state is recorded into the form to store the [EMAIL
PROTECTED] org.apache.tapestry5.PrimaryKeyEncoder#toKey(Object)
+ * primary key} for each row (rather than the index), and restore the
[EMAIL PROTECTED]
+ * org.apache.tapestry5.PrimaryKeyEncoder#toValue(java.io.Serializable)
row values} from the primary keys.
+ */
+ @Parameter
+ private PrimaryKeyEncoder encoder;
+
+ /**
* The name of the psuedo-zone that encloses the Grid.
*/
@Property(write = false)
@@ -229,7 +239,6 @@
@Environmental
private ClientBehaviorSupport clientBehaviorSupport;
- @SuppressWarnings("unused")
@Component(
parameters = {
"index=inherit:columnIndex",
@@ -238,7 +247,6 @@
"zone=zone"})
private GridColumns columns;
- @SuppressWarnings("unused")
@Component(
parameters = {
"rowIndex=inherit:rowIndex",
@@ -249,6 +257,7 @@
"row=row",
"overrides=overrides",
"volatile=inherit:volatile",
+ "encoder=inherit:encoder",
"lean=inherit:lean"})
private GridRows rows;
@@ -259,15 +268,12 @@
"zone=zone"})
private GridPager pager;
- @SuppressWarnings("unused")
@Component(parameters = "to=pagerTop")
private Delegate pagerTop;
- @SuppressWarnings("unused")
@Component(parameters = "to=pagerBottom")
private Delegate pagerBottom;
- @SuppressWarnings("unused")
@Component(parameters = "class=tableClass", inheritInformalParameters =
true)
private Any table;
@@ -297,17 +303,24 @@
/**
* A version of GridDataSource that caches the availableRows property.
This addresses TAPESTRY-2245.
*/
- class CachingDataSource implements GridDataSource
+ static class CachingDataSource implements GridDataSource
{
+ private final GridDataSource delegate;
+
private boolean availableRowsCached;
private int availableRows;
+ CachingDataSource(GridDataSource delegate)
+ {
+ this.delegate = delegate;
+ }
+
public int getAvailableRows()
{
if (!availableRowsCached)
{
- availableRows = source.getAvailableRows();
+ availableRows = delegate.getAvailableRows();
availableRowsCached = true;
}
@@ -316,17 +329,17 @@
public void prepare(int startIndex, int endIndex, List<SortConstraint>
sortConstraints)
{
- source.prepare(startIndex, endIndex, sortConstraints);
+ delegate.prepare(startIndex, endIndex, sortConstraints);
}
public Object getRowValue(int index)
{
- return source.getRowValue(index);
+ return delegate.getRowValue(index);
}
public Class getRowType()
{
- return source.getRowType();
+ return delegate.getRowType();
}
}
@@ -449,7 +462,12 @@
void setupDataSource()
{
- cachingSource = new CachingDataSource();
+ // TAP5-34: We pass the source into the CachingDataSource now;
previously
+ // we were accessing source directly, but during submit the value
wasn't
+ // cached, and therefore access was very inefficient, and sorting was
+ // very inconsistent during the processing of the form submission.
+
+ cachingSource = new CachingDataSource(source);
int availableRows = cachingSource.getAvailableRows();
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.xdoc
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.xdoc?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.xdoc
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.xdoc
Thu Oct 30 17:18:24 2008
@@ -3,10 +3,13 @@
<section name="Related Components">
<ul>
<li>
- <a href="BeanEditForm">BeanEditForm</a>
+ <a href="BeanEditForm.html">BeanEditForm</a>
</li>
<li>
- <a href="BeanDisplay">BeanDisplay</a>
+ <a href="BeanDisplay.html">BeanDisplay</a>
+ </li>
+ <li>
+ <a href="Loop.html"></a>
</li>
</ul>
</section>
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/GridRows.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/GridRows.java?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/GridRows.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/GridRows.java
Thu Oct 30 17:18:24 2008
@@ -28,6 +28,7 @@
package org.apache.tapestry5.corelib.components;
import org.apache.tapestry5.ComponentAction;
+import org.apache.tapestry5.PrimaryKeyEncoder;
import org.apache.tapestry5.PropertyOverrides;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Parameter;
@@ -40,6 +41,7 @@
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.services.FormSupport;
+import java.io.Serializable;
import java.util.List;
/**
@@ -50,17 +52,24 @@
* form render and the form submission, this can cause unexpected results,
including applying changes to the wrong
* objects.
*/
[EMAIL PROTECTED]({"unchecked"})
public class GridRows
{
private int startRow;
- static class SetupForRow implements ComponentAction<GridRows>
+ private boolean recordStateByIndex;
+ private boolean recordStateByEncoder;
+
+ /**
+ * This action is used when a [EMAIL PROTECTED]
org.apache.tapestry5.PrimaryKeyEncoder} is not.
+ */
+ static class SetupForRowByIndex implements ComponentAction<GridRows>
{
private static final long serialVersionUID = -3216282071752371975L;
private final int rowIndex;
- public SetupForRow(int rowIndex)
+ public SetupForRowByIndex(int rowIndex)
{
this.rowIndex = rowIndex;
}
@@ -73,7 +82,57 @@
@Override
public String toString()
{
- return String.format("GridRows.SetupForRow[%d]", rowIndex);
+ return String.format("GridRows.SetupForRowByIndex[%d]", rowIndex);
+ }
+ }
+
+ /**
+ * This action is used when a [EMAIL PROTECTED]
org.apache.tapestry5.PrimaryKeyEncoder} is provided.
+ */
+ static class SetupForRowByKey implements ComponentAction<GridRows>
+ {
+ private final Serializable rowKey;
+
+ SetupForRowByKey(Serializable rowKey)
+ {
+ this.rowKey = rowKey;
+ }
+
+ public void execute(GridRows component)
+ {
+ component.setupForRowByKey(rowKey);
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("GridRows.SetupForRowByKey[%s]", rowKey);
+ }
+ }
+
+
+ /**
+ * This action is also associated with the [EMAIL PROTECTED]
org.apache.tapestry5.PrimaryKeyEncoder}; it allows the PKE to be
+ * informed of the series of keys to expect with the form submission.
+ */
+ static class PrepareForKeys implements ComponentAction<GridRows>
+ {
+ private List<Serializable> storedKeys;
+
+ public PrepareForKeys(List<Serializable> storedKeys)
+ {
+ this.storedKeys = storedKeys;
+ }
+
+ public void execute(GridRows component)
+ {
+ component.prepareForKeys(storedKeys);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "GridRows.PrepareForKeys" + storedKeys.toString();
}
}
@@ -133,6 +192,14 @@
private boolean volatileState;
/**
+ * Changes how state is recorded into the form to store the [EMAIL
PROTECTED] org.apache.tapestry5.PrimaryKeyEncoder#toKey(Object)
+ * primary key} for each row (rather than the index), and restore the
[EMAIL PROTECTED]
+ * org.apache.tapestry5.PrimaryKeyEncoder#toValue(java.io.Serializable)
row values} from the primary keys.
+ */
+ @Parameter
+ private PrimaryKeyEncoder encoder;
+
+ /**
* Optional output parameter (only set during rendering) that identifies
the current row index. This is the index on
* the page (i.e., always numbered from zero) as opposed to the row index
inside the [EMAIL PROTECTED]
* org.apache.tapestry5.grid.GridDataSource}.
@@ -147,11 +214,9 @@
@Property
private int columnIndex;
-
@Environmental(false)
private FormSupport formSupport;
- private boolean recordingStateInsideForm;
private int endRow;
@@ -165,6 +230,8 @@
@Property(write = false)
private PropertyModel columnModel;
+ private List<Serializable> encodedPrimaryKeys;
+
public String getRowClass()
{
List<String> classes = CollectionFactory.newList();
@@ -227,7 +294,20 @@
dataRowIndex = startRow;
- recordingStateInsideForm = !volatileState && formSupport != null;
+ boolean recordingStateInsideForm = !volatileState && formSupport !=
null;
+
+ recordStateByIndex = recordingStateInsideForm && (encoder == null);
+ recordStateByEncoder = recordingStateInsideForm && (encoder != null);
+
+ if (recordStateByEncoder)
+ {
+ encodedPrimaryKeys = CollectionFactory.newList();
+
+ // As we render, we'll fill in encodedPrimaryKeys. That's ok,
because nothing is serialized
+ // until later. When the form is submitted, this will give us a
chance to inform
+ // the PKE about the keys to expect.
+ formSupport.store(this, new PrepareForKeys(encodedPrimaryKeys));
+ }
}
/**
@@ -238,19 +318,55 @@
row = gridModel.getDataSource().getRowValue(rowIndex);
}
- boolean beginRender()
+ /**
+ * Callback method that bypasses the data source and converts a primary
key back into a row value (via [EMAIL PROTECTED]
+ * org.apache.tapestry5.PrimaryKeyEncoder#toValue(java.io.Serializable)}).
+ */
+ void setupForRowByKey(Serializable rowKey)
{
- // When needed, store a callback used when the form is submitted.
+ row = encoder.toValue(rowKey);
- if (recordingStateInsideForm) formSupport.store(this, new
SetupForRow(dataRowIndex));
+ if (row == null)
+ throw new IllegalArgumentException(
+ String.format("%s returned null for key %s.", encoder,
rowKey));
+ }
+
+ /**
+ * Callback method that allows the primary key encoder to prepare for the
keys that will be resolved to row values
+ * in this request.
+ */
+ private void prepareForKeys(List<Serializable> storedKeys)
+ {
+ encoder.prepareForKeys(storedKeys);
+ }
- // And do it now for the render.
+
+ boolean beginRender()
+ {
+ // Setup for this row.
setupForRow(dataRowIndex);
// Update the index parameter (which starts from zero).
rowIndex = dataRowIndex - startRow;
+
+ if (row != null)
+ {
+ // When needed, store a callback used when the form is submitted.
+
+ if (recordStateByIndex)
+ formSupport.store(this, new SetupForRowByIndex(dataRowIndex));
+
+ if (recordStateByEncoder)
+ {
+ Serializable key = encoder.toKey(row);
+ encodedPrimaryKeys.add(key);
+
+ formSupport.store(this, new SetupForRowByKey(key));
+ }
+ }
+
// If the row is null, it's because the rowIndex is too large (see the
notes
// on GridDataSource). When row is null, return false to not render
anything for this iteration
// of the loop.
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Loop.xdoc
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Loop.xdoc?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Loop.xdoc
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Loop.xdoc
Thu Oct 30 17:18:24 2008
@@ -38,25 +38,22 @@
public class NavBar
{
@Parameter(defaultPrefix="literal", required=true)
- private String _pages;
+ private String pages;
@Inject
- private ComponentResources _resources;
+ private ComponentResources resources;
+ @Property
private String _pageName;
- public String getPageName() { return _pageName; }
-
- public void setPageName(String pageName) { _pageName = pageName; }
-
public String[] getPageNames()
{
- return _pages.split(",");
+ return pages.split(",");
}
public String getTabClass()
{
- if (_pageName.equalsIgnoreCase(_resources.getPageName())
+ if (pageName.equalsIgnoreCase(resources.getPageName())
return "current";
return null;
@@ -162,9 +159,10 @@
public class EditOrder
{
@Inject
- private OrderDAO _orderDAO;
+ private OrderDAO orderDAO;
- private final PrimaryKeyEncoder<Long,LineItem> _encoder = new
PrimaryKeyEncoder<Long,LineItem>()
+ @Property
+ private final PrimaryKeyEncoder<Long,LineItem> encoder = new
PrimaryKeyEncoder<Long,LineItem>()
{
public Long toKey(LineItem value) { return value.getId(); }
@@ -172,25 +170,20 @@
public LineItem toValue(Long key)
{
- return _orderDAO.getLineItem(key);
+ return orderDAO.getLineItem(key);
}
};
@Persist
- private long _orderId;
-
- private LineItem _item;
+ private long orderId;
- public PrimaryKeyEncoder getEncoder() { return _encoder ; }
+ @Property
+ private LineItem item;
public List<LineItem> getItems()
{
- return _orderDAO.getLineItemsForOrder(_orderId);
+ return orderDAO.getLineItemsForOrder(orderId);
}
-
- public LineItem getItem() { return _item; }
-
- public void setLineItem(LineItem item) { _item = item; }
}]]></source>
<p>
@@ -202,7 +195,8 @@
<p>
We've glossed over a few issues here, including how to
handle
the case that a particular item has been deleted or changed
- between the render request and the form submission.
+ between the render request and the form submission, as
well as how the orderId
+ property gets set in the first place.
</p>
<p>
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassTransformerImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassTransformerImpl.java?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassTransformerImpl.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentClassTransformerImpl.java
Thu Oct 30 17:18:24 2008
@@ -131,7 +131,8 @@
String classname = ctClass.getName();
- Logger logger = loggerSource.getLogger("tapestry.transfomer." +
classname);
+ Logger transformLogger = loggerSource.getLogger("tapestry.transfomer."
+ classname);
+ Logger logger = loggerSource.getLogger(classname);
// If the parent class is in a controlled package, it will already
have been loaded and
// transformed (that is driven by the ComponentInstantiatorSource).
@@ -175,7 +176,8 @@
throw new TransformationException(transformation, ex);
}
- logger.debug(TapestryMarkers.CLASS_TRANSFORMATION, "Finished class
transformation: {}", transformation);
+ transformLogger.debug(TapestryMarkers.CLASS_TRANSFORMATION, "Finished
class transformation: {}",
+ transformation);
nameToClassTransformation.put(classname, transformation);
nameToComponentModel.put(classname, model);
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/util/DefaultPrimaryKeyEncoder.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/util/DefaultPrimaryKeyEncoder.java?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/util/DefaultPrimaryKeyEncoder.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/util/DefaultPrimaryKeyEncoder.java
Thu Oct 30 17:18:24 2008
@@ -25,10 +25,10 @@
import java.util.Set;
/**
- * A default, extensible version of [EMAIL PROTECTED] PrimaryKeyEncoder} that
is based on loading known values into an internal
- * map. When there's a reasonable number (hundreds, perhaps thousands) of
items to choose from, and those items are fast
- * and cheap to read and instantiate, this implementation is a good bet. For
very large result sets, you'll need to
- * create your own implementation of [EMAIL PROTECTED] PrimaryKeyEncoder}.
+ * A default, extensible version of [EMAIL PROTECTED]
org.apache.tapestry5.PrimaryKeyEncoder} that is based on loading known values
+ * into an internal map. When there's a reasonable number (hundreds, perhaps
thousands) of items to choose from, and
+ * those items are fast and cheap to read and instantiate, this implementation
is a good bet. For very large result
+ * sets, you'll need to create your own implementation of [EMAIL PROTECTED]
PrimaryKeyEncoder}.
*
* @param <K> the key type (which must be serializable)
* @param <V> the value type
Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/GridFormDemo.tml
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/GridFormDemo.tml?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/GridFormDemo.tml
(original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/GridFormDemo.tml Thu
Oct 30 17:18:24 2008
@@ -1,35 +1,38 @@
<html t:type="Border"
- xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+ xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
- <h1>Grid Form Demo</h1>
+ <h1>Grid Form Demo</h1>
- <t:form>
+ <t:form>
- <t:errors />
+ <t:errors/>
- <table t:type="Grid" source="items" row="item" pagerposition="top"
- rowsperpage="5">
+ <table t:type="Grid" source="items" row="item" pagerposition="top"
+ add="id" reorder="id,title,urgency"
+ rowsperpage="5">
- <t:parameter name="titleCell">
- <t:textfield t:id="title" value="item.title" />
- </t:parameter>
+ <t:parameter name="idCell">${item.id}</t:parameter>
- <t:parameter name="urgencyCell">
- <t:select t:id="urgency" value="item.urgency" />
- </t:parameter>
+ <t:parameter name="titleCell">
+ <t:textfield t:id="title" value="item.title"/>
+ </t:parameter>
- </table>
+ <t:parameter name="urgencyCell">
+ <t:select t:id="urgency" value="item.urgency"/>
+ </t:parameter>
- <p>
- <input type="submit" value="Update Items" />
- </p>
- </t:form>
+ </table>
+
+ <p>
+ <input type="submit" value="Update Items"/>
+ </p>
+ </t:form>
- <p>
- [
- <a t:type="ActionLink" t:id="reset">reset</a>
- ]
- </p>
+ <p>
+ [
+ <a t:type="ActionLink" t:id="reset">reset</a>
+ ]
+ </p>
</html>
Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/GridFormEncoderDemo.tml
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/GridFormEncoderDemo.tml?rev=709306&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/GridFormEncoderDemo.tml
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/app1/GridFormEncoderDemo.tml
Thu Oct 30 17:18:24 2008
@@ -0,0 +1,39 @@
+<html t:type="Border"
+ xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+
+ <h1>Grid Form Encoder Demo</h1>
+
+
+ <t:form>
+
+ <t:errors/>
+
+ <table t:type="Grid" source="items" row="item" pagerposition="top"
+ encoder="encoder"
+ add="id" reorder="id,title,urgency"
+ rowsperpage="5">
+
+ <t:parameter name="idCell">${item.id}</t:parameter>
+
+ <t:parameter name="titleCell">
+ <t:textfield t:id="title" value="item.title"/>
+ </t:parameter>
+
+ <t:parameter name="urgencyCell">
+ <t:select t:id="urgency" value="item.urgency"/>
+ </t:parameter>
+
+ </table>
+
+ <p>
+ <input type="submit" value="Update Items"/>
+ </p>
+ </t:form>
+
+
+ <p>
+ [
+ <a t:type="ActionLink" t:id="reset">reset</a>
+ ]
+ </p>
+</html>
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
Thu Oct 30 17:18:24 2008
@@ -1159,6 +1159,28 @@
}
@Test
+ public void grid_inside_form_with_encoder()
+ {
+ start("Grid Form Encoder Demo", "reset", "2");
+
+ // The first input field is the form's hidden field.
+
+ assertFieldValue("title", "ToDo # 6");
+ assertFieldValueSeries("title_%d", 0, "ToDo # 7", "ToDo # 8", "ToDo #
9", "ToDo # 10");
+
+ type("title_0", "Cure Cancer");
+ select("urgency_0", "Top Priority");
+
+ type("title_1", "Pay Phone Bill");
+ select("urgency_1", "Low");
+
+ clickAndWait(SUBMIT);
+
+ assertFieldValueSeries("title_%d", 0, "Cure Cancer", "Pay Phone Bill");
+ assertFieldValueSeries("urgency_%d", 0, "HIGH", "LOW");
+ }
+
+ @Test
public void missing_template_for_page()
{
start("Missing Template Demo");
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/GridFormDemo.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/GridFormDemo.java?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/GridFormDemo.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/GridFormDemo.java
Thu Oct 30 17:18:24 2008
@@ -72,5 +72,4 @@
database.add(item);
}
}
-
}
Added:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/GridFormEncoderDemo.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/GridFormEncoderDemo.java?rev=709306&view=auto
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/GridFormEncoderDemo.java
(added)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/GridFormEncoderDemo.java
Thu Oct 30 17:18:24 2008
@@ -0,0 +1,20 @@
+package org.apache.tapestry5.integration.app1.pages;
+
+import org.apache.tapestry5.PrimaryKeyEncoder;
+import org.apache.tapestry5.integration.app1.data.ToDoItem;
+import org.apache.tapestry5.util.DefaultPrimaryKeyEncoder;
+
+public class GridFormEncoderDemo extends GridFormDemo
+{
+ public PrimaryKeyEncoder<Long, ToDoItem> getEncoder()
+ {
+ DefaultPrimaryKeyEncoder<Long, ToDoItem> result = new
DefaultPrimaryKeyEncoder<Long, ToDoItem>();
+
+ for (ToDoItem item : getItems())
+ {
+ result.add(item.getId(), item);
+ }
+
+ return result;
+ }
+}
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Start.java
Thu Oct 30 17:18:24 2008
@@ -65,6 +65,9 @@
private static final List<Item> ITEMS = CollectionFactory.newList(
+ new Item("GridFormEncoderDemo", "Grid Form Encoder Demo",
+ "Grid inside a Form using the PrimaryKeyEncoder option"),
+
new Item("DateFieldAjaxFormLoop", "DateField inside AjaxFormLoop",
"Show that DateField component works correctly inside
AjaxFormLoop"),
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/ToDoDatabase.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/ToDoDatabase.java?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/ToDoDatabase.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/ToDoDatabase.java
Thu Oct 30 17:18:24 2008
@@ -55,4 +55,9 @@
* @throws RuntimeException if the item does not exist
*/
void remove(long itemId);
+
+ /**
+ * Gets the item, or returns null.
+ */
+ ToDoItem get(long itemId);
}
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/ToDoDatabaseImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/ToDoDatabaseImpl.java?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/ToDoDatabaseImpl.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/services/ToDoDatabaseImpl.java
Thu Oct 30 17:18:24 2008
@@ -114,5 +114,10 @@
throw new RuntimeException(String.format("ToDoItem #%d not
found.", itemId));
}
+ public ToDoItem get(long itemId)
+ {
+ ToDoItem item = items.get(itemId);
+ return item == null ? null : item.clone();
+ }
}
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/log4j.properties
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/log4j.properties?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/log4j.properties
(original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/log4j.properties
Thu Oct 30 17:18:24 2008
@@ -19,9 +19,9 @@
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
-log4j.appender.A1.layout.ConversionPattern= %d{HH:mm:ss,SSS} [%p] %c{1} %m%n
+log4j.appender.A1.layout.ConversionPattern=[%p] %c{1} %m%n
log4j.category.org.apache.tapestry5.integration.app2=debug
-# log4j.category.org.apache.tapestry5.corelib.components=debug
+log4j.category.org.apache.tapestry5.corelib.components.Form=debug
Modified:
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/CtClassSourceImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/CtClassSourceImpl.java?rev=709306&r1=709305&r2=709306&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/CtClassSourceImpl.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/CtClassSourceImpl.java
Thu Oct 30 17:18:24 2008
@@ -26,6 +26,8 @@
*/
public class CtClassSourceImpl implements CtClassSource
{
+ private static final String WRITE_DIR =
System.getProperty("javassist-write-dir");
+
private final ClassFactoryClassPool pool;
private final ClassLoader loader;
@@ -81,7 +83,6 @@
return pool.makeClass(name, ctSuperClass);
}
- private static final String WRITE_DIR =
System.getProperty("javassist-write-dir");
public Class createClass(CtClass ctClass)
{
@@ -108,13 +109,7 @@
{
try
{
- boolean pruning = ctClass.stopPruning(true);
-
- ctClass.writeFile(WRITE_DIR);
-
- ctClass.defrost();
-
- ctClass.stopPruning(pruning);
+ ctClass.debugWriteFile(WRITE_DIR);
}
catch (Exception ex)
{