You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by mi...@apache.org on 2005/08/02 23:39:56 UTC
cvs commit: jakarta-tapestry/framework/src/java/org/apache/tapestry/components ForBean.java For.jwc
mindbridge 2005/08/02 14:39:56
Modified: framework/src/java/org/apache/tapestry/components
ForBean.java For.jwc
Log:
A more efficient version of the For component
Revision Changes Path
1.2 +235 -172 jakarta-tapestry/framework/src/java/org/apache/tapestry/components/ForBean.java
Index: ForBean.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/components/ForBean.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ForBean.java 4 Jul 2005 21:31:38 -0000 1.1
+++ ForBean.java 2 Aug 2005 21:39:56 -0000 1.2
@@ -16,6 +16,7 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -39,6 +40,9 @@
public abstract class ForBean extends AbstractFormComponent {
private static final char DESC_VALUE = 'V';
private static final char DESC_PRIMARY_KEY = 'P';
+
+ private static final String PARAMETER_SOURCE = "source";
+ private static final String PARAMETER_FULL_SOURCE = "fullSource";
// parameters
public abstract Object getSource();
@@ -53,6 +57,8 @@
// properties
public abstract Map getPrimaryKeyMap();
public abstract void setPrimaryKeyMap(Map primaryKeys);
+ public abstract Map getSourceIteratorMap();
+ public abstract void setSourceIteratorMap(Map sourceIteratorMap);
// injects
public abstract DataSqueezer getDataSqueezer();
@@ -63,113 +69,7 @@
private Object _value;
private int _index;
private boolean _rendering;
-
- /**
- * Gets the source binding and returns an {@link Iterator}
- * representing
- * the values identified by the source. Returns an empty {@link Iterator}
- * if the binding, or the binding value, is null.
- *
- * <p>Invokes {@link Tapestry#coerceToIterator(Object)} to perform
- * the actual conversion.
- *
- **/
-
- protected Iterator getSourceData()
- {
- Object source = getSource();
- if (source == null)
- return null;
-
- Iterator iteratorSource = (Iterator) getValueConverter().coerceValue(source, Iterator.class);
-
- return iteratorSource;
- }
-
- protected Iterator storeSourceData(IForm form, String name)
- {
- Iterator iteratorSource = getSourceData();
- if (iteratorSource == null)
- return null;
-
- // extract primary keys from data
- StringBuffer pkDesc = new StringBuffer();
- List data = new ArrayList();
- List pks = new ArrayList();
- while (iteratorSource.hasNext()) {
- Object value = iteratorSource.next();
- data.add(value);
-
- Object pk = getPrimaryKeyFromValue(value);
- if (pk == null) {
- pk = value;
- pkDesc.append(DESC_VALUE);
- }
- else
- pkDesc.append(DESC_PRIMARY_KEY);
- pks.add(pk);
- }
-
- // store primary keys
- form.addHiddenValue(name, pkDesc.toString());
- for (Iterator it = pks.iterator(); it.hasNext();) {
- Object pk = it.next();
- try {
- String stringRep = getDataSqueezer().squeeze(pk);
- form.addHiddenValue(name, stringRep);
- } catch (IOException ex) {
- throw new ApplicationRuntimeException(
- Tapestry.format("For.unable-to-convert-value", pk),
- this,
- null,
- ex);
- }
- }
- return data.iterator();
- }
-
- protected Iterator getStoredData(IRequestCycle cycle, String name)
- {
- String[] submittedPrimaryKeys = cycle.getParameters(name);
- String pkDesc = submittedPrimaryKeys[0];
-
- // unsqueeze data
- List data = new ArrayList(submittedPrimaryKeys.length-1);
- List pks = new ArrayList(submittedPrimaryKeys.length-1);
- for (int i = 1; i < submittedPrimaryKeys.length; i++) {
- String stringRep = submittedPrimaryKeys[i];
- try {
- Object value = getDataSqueezer().unsqueeze(stringRep);
- data.add(value);
- if (i <= pkDesc.length() && pkDesc.charAt(i-1) == DESC_PRIMARY_KEY)
- pks.add(value);
- } catch (IOException ex) {
- throw new ApplicationRuntimeException(
- Tapestry.format("For.unable-to-convert-string", stringRep),
- this,
- null,
- ex);
- }
- }
-
- // update the binding with the list of primary keys
- IBinding primaryKeysBinding = getBinding("primaryKeys");
- if (primaryKeysBinding != null)
- primaryKeysBinding.setObject(pks);
-
- // convert from primary keys to data
- for (int i = 0; i < data.size(); i++) {
- if (i <= pkDesc.length() && pkDesc.charAt(i) == DESC_PRIMARY_KEY) {
- Object pk = data.get(i);
- Object value = getValueFromPrimaryKey(pk);
- data.set(i, value);
- }
- }
-
- return data.iterator();
- }
-
/**
* Gets the source binding and iterates through
* its values. For each, it updates the value binding and render's its wrapped elements.
@@ -187,21 +87,8 @@
if (cycleRewinding && form != null && !form.isRewinding())
return;
- boolean bInForm = (form != null && !getVolatile());
-
- String name = "";
- if (form != null)
- name = form.getElementId(this);
-
// Get the data to be iterated upon. Store in form if needed.
- Iterator dataSource;
- if (!bInForm)
- dataSource = getSourceData();
- else if (cycleRewinding)
- dataSource = getStoredData(cycle, name);
- else
- dataSource = storeSourceData(form, name);
-
+ Iterator dataSource = getData(cycle, form);
// Do not iterate if dataSource is null.
// The dataSource was either not convertable to Iterator, or was empty.
@@ -222,13 +109,7 @@
_value = dataSource.next();
// Update output component parameters
- IBinding indexBinding = getBinding("index");
- if (indexBinding != null)
- indexBinding.setObject(new Integer(_index));
-
- IBinding valueBinding = getBinding("value");
- if (valueBinding != null)
- valueBinding.setObject(_value);
+ updateOutputParameters();
// Render component
if (element != null)
@@ -251,31 +132,160 @@
_value = null;
}
}
-
- private Object restoreValue(IForm form, String name, Object primaryKey)
+
+
+ /**
+ * Returns a list with the values to be iterated upon.
+ *
+ * The list is obtained in different ways:
+ * - If the component is not located in a form or 'volatile' is set to true,
+ * then the simply the values passed to 'source' are returned (same as Foreach)
+ * - If the component is in a form, and the form is rewinding, the values stored
+ * in the form are returned -- rewind is then always the same as render.
+ * - If the component is in a form, and the form is being rendered, the values
+ * are stored in the form as Hidden fields.
+ *
+ * @param cycle The current request cycle
+ * @param form The form within which the component is located (if any)
+ * @return An iterator with the values to be cycled upon
+ **/
+ private Iterator getData(IRequestCycle cycle, IForm form) {
+ if (form == null || getVolatile())
+ return getSource(PARAMETER_SOURCE);
+
+ String name = form.getElementId(this);
+ if (cycle.isRewinding())
+ return getStoredData(cycle, name);
+ else
+ return storeSourceData(form, name);
+ }
+
+ /**
+ * Returns an {@link Iterator} containing the values provided
+ * by the identified source binding.
+ *
+ * @param parameter The name of the source binding
+ * @return an iterator with the bound values. null if the parameter is not bound
+ * or the conversion cannot be performed
+ **/
+ protected Iterator getSource(String parameter)
+ {
+ IBinding binding = getBinding(parameter);
+ if (binding == null)
+ return null;
+
+ Object data = binding.getObject();
+ return (Iterator) getValueConverter().coerceValue(data, Iterator.class);
+ }
+
+ /**
+ * Returns a list of the values stored as Hidden fields in the form.
+ * A conversion is performed if the primary key of the value is stored.
+ *
+ * @param cycle The current request cycle
+ * @param name The name of the HTTP parameter whether the values
+ * @return an iterator with the values stored in the provided Hidden fields
+ **/
+ protected Iterator getStoredData(IRequestCycle cycle, String name)
{
- return getValueFromPrimaryKey(primaryKey);
+ String[] submittedPrimaryKeys = cycle.getParameters(name);
+ String pkDesc = submittedPrimaryKeys[0];
+
+ // unsqueeze data
+ List data = new ArrayList(submittedPrimaryKeys.length-1);
+ List pks = new ArrayList(submittedPrimaryKeys.length-1);
+ for (int i = 1; i < submittedPrimaryKeys.length; i++) {
+ String stringRep = submittedPrimaryKeys[i];
+ try {
+ Object value = getDataSqueezer().unsqueeze(stringRep);
+ data.add(value);
+ if (i <= pkDesc.length() && pkDesc.charAt(i-1) == DESC_PRIMARY_KEY)
+ pks.add(value);
+ } catch (IOException ex) {
+ throw new ApplicationRuntimeException(
+ Tapestry.format("For.unable-to-convert-string", stringRep),
+ this,
+ null,
+ ex);
+ }
+ }
+
+ // update the binding with the list of primary keys
+ IBinding primaryKeysBinding = getBinding("primaryKeys");
+ if (primaryKeysBinding != null)
+ primaryKeysBinding.setObject(pks);
+
+ // convert from primary keys to data
+ for (int i = 0; i < data.size(); i++) {
+ if (i <= pkDesc.length() && pkDesc.charAt(i) == DESC_PRIMARY_KEY) {
+ Object pk = data.get(i);
+ Object value = getValueFromPrimaryKey(pk);
+ data.set(i, value);
+ }
+ }
+
+ return data.iterator();
}
- private void storeValue(IForm form, String name, Object value)
+ /**
+ * Stores the provided data in the form and then returns the data as an iterator.
+ * If the primary key of the value can be determined,
+ * then that primary key is saved instead.
+ *
+ * @param form The form where the data will be stored
+ * @param name The name under which the data will be stored
+ * @return an iterator with the bound values stored in the form
+ **/
+ protected Iterator storeSourceData(IForm form, String name)
{
- Object convertedValue = getPrimaryKeyFromValue(value);
+ Iterator iteratorSource = getSource(PARAMETER_SOURCE);
+ if (iteratorSource == null)
+ return null;
- try
- {
- String externalValue = getDataSqueezer().squeeze(convertedValue);
- form.addHiddenValue(name, externalValue);
- }
- catch (IOException ex)
- {
- throw new ApplicationRuntimeException(
- Tapestry.format("For.unable-to-convert-value", value),
- this,
- null,
- ex);
- }
+ // extract primary keys from data
+ StringBuffer pkDesc = new StringBuffer();
+ List data = new ArrayList();
+ List pks = new ArrayList();
+ while (iteratorSource.hasNext()) {
+ Object value = iteratorSource.next();
+ data.add(value);
+
+ Object pk = getPrimaryKeyFromValue(value);
+ if (pk == null) {
+ pk = value;
+ pkDesc.append(DESC_VALUE);
+ }
+ else
+ pkDesc.append(DESC_PRIMARY_KEY);
+ pks.add(pk);
+ }
+
+ // store primary keys
+ form.addHiddenValue(name, pkDesc.toString());
+ for (Iterator it = pks.iterator(); it.hasNext();) {
+ Object pk = it.next();
+ try {
+ String stringRep = getDataSqueezer().squeeze(pk);
+ form.addHiddenValue(name, stringRep);
+ } catch (IOException ex) {
+ throw new ApplicationRuntimeException(
+ Tapestry.format("For.unable-to-convert-value", pk),
+ this,
+ null,
+ ex);
+ }
+ }
+
+ return data.iterator();
}
+ /**
+ * Returns the primary key of the given value.
+ * Uses the 'keyExpression' or the 'converter' (if either is provided).
+ *
+ * @param value The value from which the primary key should be extracted
+ * @return The primary key of the value, or null if such cannot be extracted.
+ */
private Object getPrimaryKeyFromValue(Object value) {
Object primaryKey = null;
@@ -292,18 +302,20 @@
return primaryKey;
}
+ /**
+ * Returns a value that corresponds to the provided primary key.
+ * Uses either the 'keyExpression' if provided
+ *
+ * @param primaryKey
+ * @return
+ */
private Object getValueFromPrimaryKey(Object primaryKey) {
Object value = null;
- if (value == null && getKeyExpression() != null) {
- String keyExpression = getKeyExpression();
- if (keyExpression != null) {
- Map primaryKeys = getPrimaryKeyMap();
- if (primaryKeys == null)
- primaryKeys = initializePrimaryKeysFromSource(keyExpression);
- value = primaryKeys.get(primaryKeys);
- }
- }
+ // if keyExpression is defined, try to get the object in that way
+ String keyExpression = getKeyExpression();
+ if (keyExpression != null)
+ value = getValueFromExpressionPrimaryKeys(keyExpression, primaryKey);
if (value == null) {
IPrimaryKeyConverter converter = getConverter();
@@ -317,28 +329,79 @@
return value;
}
- private Map initializePrimaryKeysFromSource(String keyExpression)
+ private Object getValueFromExpressionPrimaryKeys(String keyExpression, Object primaryKey)
{
- Map primaryKeys = new HashMap();
-
- Object fullSource = getFullSource();
- if (fullSource == null)
- fullSource = getSource();
- if (fullSource == null)
- return primaryKeys;
+ Object value = null;
- ExpressionEvaluator evaluator = getExpressionEvaluator();
+ Map primaryKeys = getPrimaryKeyMap();
+ if (primaryKeys == null)
+ primaryKeys = new HashMap();
+ else {
+ value = primaryKeys.get(primaryKey);
+ if (value != null)
+ return value;
+ }
+
+ ExpressionEvaluator evaluator = getExpressionEvaluator();
+
+ // Iterate over the elements in 'source' and 'fullSource' until a primary key match is found
+ value = findPrimaryKeyMatch(primaryKey, PARAMETER_SOURCE);
+ if (value == null)
+ value = findPrimaryKeyMatch(primaryKey, PARAMETER_FULL_SOURCE);
+
+ return value;
+ }
+
+ private Object findPrimaryKeyMatch(Object primaryKey, String parameter)
+ {
+ ExpressionEvaluator evaluator = getExpressionEvaluator();
+ String keyExpression = getKeyExpression();
+
+ Map primaryKeys = getPrimaryKeyMap();
+ if (primaryKeys == null)
+ primaryKeys = new HashMap();
- Iterator iteratorSource = (Iterator) getValueConverter().coerceValue(fullSource, Iterator.class);
- while (iteratorSource.hasNext()) {
- Object value = iteratorSource.next();
- Object primaryKey = evaluator.read(value, keyExpression);
- if (primaryKey != null)
- primaryKeys.put(primaryKey, value);
- }
+ Map sourceIteratorMap = getSourceIteratorMap();
+ if (sourceIteratorMap == null)
+ sourceIteratorMap = new HashMap();
- setPrimaryKeyMap(primaryKeys);
- return primaryKeys;
+ Iterator it = (Iterator) sourceIteratorMap.get(parameter);
+ if (it == null) {
+ it = getSource(parameter);
+ if (it == null)
+ it = Collections.EMPTY_LIST.iterator();
+ }
+
+ try {
+ while (it.hasNext()) {
+ Object sourceValue = it.next();
+ Object sourcePrimaryKey = evaluator.read(sourceValue, keyExpression);
+ if (sourcePrimaryKey != null)
+ primaryKeys.put(sourcePrimaryKey, sourceValue);
+
+ if (primaryKey.equals(sourcePrimaryKey)) {
+ return sourceValue;
+ }
+ }
+
+ return null;
+ }
+ finally {
+ sourceIteratorMap.put(parameter, it);
+ setSourceIteratorMap(sourceIteratorMap);
+ setPrimaryKeyMap(primaryKeys);
+ }
+ }
+
+ private void updateOutputParameters()
+ {
+ IBinding indexBinding = getBinding("index");
+ if (indexBinding != null)
+ indexBinding.setObject(new Integer(_index));
+
+ IBinding valueBinding = getBinding("value");
+ if (valueBinding != null)
+ valueBinding.setObject(_value);
}
/**
1.3 +3 -3 jakarta-tapestry/framework/src/java/org/apache/tapestry/components/For.jwc
Index: For.jwc
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/components/For.jwc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- For.jwc 28 Jul 2005 19:10:40 -0000 1.2
+++ For.jwc 2 Aug 2005 21:39:56 -0000 1.3
@@ -70,9 +70,9 @@
<parameter name="fullSource">
<description>
Only active in a form and in combination with the 'keyExpression' parameter.
- The objects provided by this parameter will be used to determine the values
- referred to by the primary keys stored in the form.
- If this parameter is not bound, 'source' is used instead.
+ If an object corresponding to a primary key stored in the form cannot be
+ found in the 'source' parameter, then the objects provided by this parameter
+ are searched for a match next.
</description>
</parameter>
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
Re: Unused variables
Posted by Mind Bridge <mi...@yahoo.com>.
Hi,
I was actually planning to make a pass just before the end of the
release cycle and remove all unused imports, unused variables, etc. I
guess I will do that sooner...
Howard Lewis Ship wrote:
>Mindbridge,
>
>I think we have different settings for compiling under Eclipse.
>
>I have unused variables set as an error, so I had to change your
>check-in to compile and run the test suite.
>
>I'm looking for a way we can share these settings.
>
>In addition we may need a discussion about what the setting should be.
>
>Especially under JDK 1.5, there are so many warnings that they no
>longer mean anything, only errors will ever get noticed.
>
>
>---------- Forwarded message ----------
>From: mindbridge@apache.org <mi...@apache.org>
>Date: 2 Aug 2005 21:39:56 -0000
>Subject: cvs commit:
>jakarta-tapestry/framework/src/java/org/apache/tapestry/components
>ForBean.java For.jwc
>To: jakarta-tapestry-cvs@apache.org
>
>
>mindbridge 2005/08/02 14:39:56
>
> Modified: framework/src/java/org/apache/tapestry/components
> ForBean.java For.jwc
> Log:
> A more efficient version of the For component
>
> Revision Changes Path
> 1.2 +235 -172
>jakarta-tapestry/framework/src/java/org/apache/tapestry/components/ForBean.java
>
> Index: ForBean.java
> ===================================================================
> RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/components/ForBean.java,v
> retrieving revision 1.1
> retrieving revision 1.2
> diff -u -r1.1 -r1.2
> --- ForBean.java 4 Jul 2005 21:31:38 -0000 1.1
> +++ ForBean.java 2 Aug 2005 21:39:56 -0000 1.2
> @@ -16,6 +16,7 @@
>
> import java.io.IOException;
> import java.util.ArrayList;
> +import java.util.Collections;
> import java.util.HashMap;
> import java.util.Iterator;
> import java.util.List;
> @@ -39,6 +40,9 @@
> public abstract class ForBean extends AbstractFormComponent {
> private static final char DESC_VALUE = 'V';
> private static final char DESC_PRIMARY_KEY = 'P';
> +
> + private static final String PARAMETER_SOURCE = "source";
> + private static final String PARAMETER_FULL_SOURCE = "fullSource";
>
> // parameters
> public abstract Object getSource();
> @@ -53,6 +57,8 @@
> // properties
> public abstract Map getPrimaryKeyMap();
> public abstract void setPrimaryKeyMap(Map primaryKeys);
> + public abstract Map getSourceIteratorMap();
> + public abstract void setSourceIteratorMap(Map sourceIteratorMap);
>
> // injects
> public abstract DataSqueezer getDataSqueezer();
> @@ -63,113 +69,7 @@
> private Object _value;
> private int _index;
> private boolean _rendering;
> -
> - /**
> - * Gets the source binding and returns an {@link Iterator}
> - * representing
> - * the values identified by the source. Returns an empty
>{@link Iterator}
> - * if the binding, or the binding value, is null.
> - *
> - * <p>Invokes {@link Tapestry#coerceToIterator(Object)} to perform
> - * the actual conversion.
> - *
> - **/
> -
> - protected Iterator getSourceData()
> - {
> - Object source = getSource();
> - if (source == null)
> - return null;
> -
> - Iterator iteratorSource = (Iterator)
>getValueConverter().coerceValue(source, Iterator.class);
> -
> - return iteratorSource;
> - }
> -
> - protected Iterator storeSourceData(IForm form, String name)
> - {
> - Iterator iteratorSource = getSourceData();
> - if (iteratorSource == null)
> - return null;
> -
> - // extract primary keys from data
> - StringBuffer pkDesc = new StringBuffer();
> - List data = new ArrayList();
> - List pks = new ArrayList();
> - while (iteratorSource.hasNext()) {
> - Object value = iteratorSource.next();
> - data.add(value);
> -
> - Object pk = getPrimaryKeyFromValue(value);
> - if (pk == null) {
> - pk = value;
> - pkDesc.append(DESC_VALUE);
> - }
> - else
> - pkDesc.append(DESC_PRIMARY_KEY);
> - pks.add(pk);
> - }
> -
> - // store primary keys
> - form.addHiddenValue(name, pkDesc.toString());
> - for (Iterator it = pks.iterator(); it.hasNext();) {
> - Object pk = it.next();
> - try {
> - String stringRep =
>getDataSqueezer().squeeze(pk);
> - form.addHiddenValue(name, stringRep);
> - } catch (IOException ex) {
> - throw new ApplicationRuntimeException(
> - Tapestry.format("For.unable-to-convert-value", pk),
> - this,
> - null,
> - ex);
> - }
> - }
>
> - return data.iterator();
> - }
> -
> - protected Iterator getStoredData(IRequestCycle cycle, String name)
> - {
> - String[] submittedPrimaryKeys = cycle.getParameters(name);
> - String pkDesc = submittedPrimaryKeys[0];
> -
> - // unsqueeze data
> - List data = new ArrayList(submittedPrimaryKeys.length-1);
> - List pks = new ArrayList(submittedPrimaryKeys.length-1);
> - for (int i = 1; i < submittedPrimaryKeys.length; i++) {
> - String stringRep = submittedPrimaryKeys[i];
> - try {
> - Object value =
>getDataSqueezer().unsqueeze(stringRep);
> - data.add(value);
> - if (i <= pkDesc.length() &&
>pkDesc.charAt(i-1) == DESC_PRIMARY_KEY)
> - pks.add(value);
> - } catch (IOException ex) {
> - throw new ApplicationRuntimeException(
> -
>Tapestry.format("For.unable-to-convert-string", stringRep),
> - this,
> - null,
> - ex);
> - }
> - }
> -
> - // update the binding with the list of primary keys
> - IBinding primaryKeysBinding = getBinding("primaryKeys");
> - if (primaryKeysBinding != null)
> - primaryKeysBinding.setObject(pks);
> -
> - // convert from primary keys to data
> - for (int i = 0; i < data.size(); i++) {
> - if (i <= pkDesc.length() && pkDesc.charAt(i) ==
>DESC_PRIMARY_KEY) {
> - Object pk = data.get(i);
> - Object value = getValueFromPrimaryKey(pk);
> - data.set(i, value);
> - }
> - }
> -
> - return data.iterator();
> - }
> -
> /**
> * Gets the source binding and iterates through
> * its values. For each, it updates the value binding and
>render's its wrapped elements.
> @@ -187,21 +87,8 @@
> if (cycleRewinding && form != null && !form.isRewinding())
> return;
>
> - boolean bInForm = (form != null && !getVolatile());
> -
> - String name = "";
> - if (form != null)
> - name = form.getElementId(this);
> -
> // Get the data to be iterated upon. Store in form if needed.
> - Iterator dataSource;
> - if (!bInForm)
> - dataSource = getSourceData();
> - else if (cycleRewinding)
> - dataSource = getStoredData(cycle, name);
> - else
> - dataSource = storeSourceData(form, name);
> -
> + Iterator dataSource = getData(cycle, form);
>
> // Do not iterate if dataSource is null.
> // The dataSource was either not convertable to Iterator,
>or was empty.
> @@ -222,13 +109,7 @@
> _value = dataSource.next();
>
> // Update output component parameters
> - IBinding indexBinding = getBinding("index");
> - if (indexBinding != null)
> - indexBinding.setObject(new Integer(_index));
> -
> - IBinding valueBinding = getBinding("value");
> - if (valueBinding != null)
> - valueBinding.setObject(_value);
> + updateOutputParameters();
>
> // Render component
> if (element != null)
> @@ -251,31 +132,160 @@
> _value = null;
> }
> }
> -
> - private Object restoreValue(IForm form, String name, Object primaryKey)
> +
> +
> + /**
> + * Returns a list with the values to be iterated upon.
> + *
> + * The list is obtained in different ways:
> + * - If the component is not located in a form or 'volatile' is
>set to true,
> + * then the simply the values passed to 'source' are returned
>(same as Foreach)
> + * - If the component is in a form, and the form is rewinding,
>the values stored
> + * in the form are returned -- rewind is then always the
>same as render.
> + * - If the component is in a form, and the form is being
>rendered, the values
> + * are stored in the form as Hidden fields.
> + *
> + * @param cycle The current request cycle
> + * @param form The form within which the component is located (if any)
> + * @return An iterator with the values to be cycled upon
> + **/
> + private Iterator getData(IRequestCycle cycle, IForm form) {
> + if (form == null || getVolatile())
> + return getSource(PARAMETER_SOURCE);
> +
> + String name = form.getElementId(this);
> + if (cycle.isRewinding())
> + return getStoredData(cycle, name);
> + else
> + return storeSourceData(form, name);
> + }
> +
> + /**
> + * Returns an {@link Iterator} containing the values provided
> + * by the identified source binding.
> + *
> + * @param parameter The name of the source binding
> + * @return an iterator with the bound values. null if the
>parameter is not bound
> + * or the conversion cannot be performed
> + **/
> + protected Iterator getSource(String parameter)
> + {
> + IBinding binding = getBinding(parameter);
> + if (binding == null)
> + return null;
> +
> + Object data = binding.getObject();
> + return (Iterator)
>getValueConverter().coerceValue(data, Iterator.class);
> + }
> +
> + /**
> + * Returns a list of the values stored as Hidden fields in the form.
> + * A conversion is performed if the primary key of the value is stored.
> + *
> + * @param cycle The current request cycle
> + * @param name The name of the HTTP parameter whether the values
> + * @return an iterator with the values stored in the provided
>Hidden fields
> + **/
> + protected Iterator getStoredData(IRequestCycle cycle, String name)
> {
> - return getValueFromPrimaryKey(primaryKey);
> + String[] submittedPrimaryKeys = cycle.getParameters(name);
> + String pkDesc = submittedPrimaryKeys[0];
> +
> + // unsqueeze data
> + List data = new ArrayList(submittedPrimaryKeys.length-1);
> + List pks = new ArrayList(submittedPrimaryKeys.length-1);
> + for (int i = 1; i < submittedPrimaryKeys.length; i++) {
> + String stringRep = submittedPrimaryKeys[i];
> + try {
> + Object value =
>getDataSqueezer().unsqueeze(stringRep);
> + data.add(value);
> + if (i <= pkDesc.length() &&
>pkDesc.charAt(i-1) == DESC_PRIMARY_KEY)
> + pks.add(value);
> + } catch (IOException ex) {
> + throw new ApplicationRuntimeException(
> +
>Tapestry.format("For.unable-to-convert-string", stringRep),
> + this,
> + null,
> + ex);
> + }
> + }
> +
> + // update the binding with the list of primary keys
> + IBinding primaryKeysBinding = getBinding("primaryKeys");
> + if (primaryKeysBinding != null)
> + primaryKeysBinding.setObject(pks);
> +
> + // convert from primary keys to data
> + for (int i = 0; i < data.size(); i++) {
> + if (i <= pkDesc.length() && pkDesc.charAt(i) ==
>DESC_PRIMARY_KEY) {
> + Object pk = data.get(i);
> + Object value = getValueFromPrimaryKey(pk);
> + data.set(i, value);
> + }
> + }
> +
> + return data.iterator();
> }
>
> - private void storeValue(IForm form, String name, Object value)
> + /**
> + * Stores the provided data in the form and then returns the
>data as an iterator.
> + * If the primary key of the value can be determined,
> + * then that primary key is saved instead.
> + *
> + * @param form The form where the data will be stored
> + * @param name The name under which the data will be stored
> + * @return an iterator with the bound values stored in the form
> + **/
> + protected Iterator storeSourceData(IForm form, String name)
> {
> - Object convertedValue = getPrimaryKeyFromValue(value);
> + Iterator iteratorSource = getSource(PARAMETER_SOURCE);
> + if (iteratorSource == null)
> + return null;
>
> - try
> - {
> - String externalValue =
>getDataSqueezer().squeeze(convertedValue);
> - form.addHiddenValue(name, externalValue);
> - }
> - catch (IOException ex)
> - {
> - throw new ApplicationRuntimeException(
> - Tapestry.format("For.unable-to-convert-value", value),
> - this,
> - null,
> - ex);
> - }
> + // extract primary keys from data
> + StringBuffer pkDesc = new StringBuffer();
> + List data = new ArrayList();
> + List pks = new ArrayList();
> + while (iteratorSource.hasNext()) {
> + Object value = iteratorSource.next();
> + data.add(value);
> +
> + Object pk = getPrimaryKeyFromValue(value);
> + if (pk == null) {
> + pk = value;
> + pkDesc.append(DESC_VALUE);
> + }
> + else
> + pkDesc.append(DESC_PRIMARY_KEY);
> + pks.add(pk);
> + }
> +
> + // store primary keys
> + form.addHiddenValue(name, pkDesc.toString());
> + for (Iterator it = pks.iterator(); it.hasNext();) {
> + Object pk = it.next();
> + try {
> + String stringRep =
>getDataSqueezer().squeeze(pk);
> + form.addHiddenValue(name, stringRep);
> + } catch (IOException ex) {
> + throw new ApplicationRuntimeException(
> + Tapestry.format("For.unable-to-convert-value", pk),
> + this,
> + null,
> + ex);
> + }
> + }
> +
> + return data.iterator();
> }
>
> + /**
> + * Returns the primary key of the given value.
> + * Uses the 'keyExpression' or the 'converter' (if either is provided).
> + *
> + * @param value The value from which the primary key should be extracted
> + * @return The primary key of the value, or null if such cannot
>be extracted.
> + */
> private Object getPrimaryKeyFromValue(Object value) {
> Object primaryKey = null;
>
> @@ -292,18 +302,20 @@
> return primaryKey;
> }
>
> + /**
> + * Returns a value that corresponds to the provided primary key.
> + * Uses either the 'keyExpression' if provided
> + *
> + * @param primaryKey
> + * @return
> + */
> private Object getValueFromPrimaryKey(Object primaryKey) {
> Object value = null;
>
> - if (value == null && getKeyExpression() != null) {
> - String keyExpression = getKeyExpression();
> - if (keyExpression != null) {
> - Map primaryKeys = getPrimaryKeyMap();
> - if (primaryKeys == null)
> - primaryKeys =
>initializePrimaryKeysFromSource(keyExpression);
> - value = primaryKeys.get(primaryKeys);
> - }
> - }
> + // if keyExpression is defined, try to get the object in that way
> + String keyExpression = getKeyExpression();
> + if (keyExpression != null)
> + value =
>getValueFromExpressionPrimaryKeys(keyExpression, primaryKey);
>
> if (value == null) {
> IPrimaryKeyConverter converter = getConverter();
> @@ -317,28 +329,79 @@
> return value;
> }
>
> - private Map initializePrimaryKeysFromSource(String keyExpression)
> + private Object getValueFromExpressionPrimaryKeys(String
>keyExpression, Object primaryKey)
> {
> - Map primaryKeys = new HashMap();
> -
> - Object fullSource = getFullSource();
> - if (fullSource == null)
> - fullSource = getSource();
> - if (fullSource == null)
> - return primaryKeys;
> + Object value = null;
>
> - ExpressionEvaluator evaluator = getExpressionEvaluator();
> + Map primaryKeys = getPrimaryKeyMap();
> + if (primaryKeys == null)
> + primaryKeys = new HashMap();
> + else {
> + value = primaryKeys.get(primaryKey);
> + if (value != null)
> + return value;
> + }
> +
> + ExpressionEvaluator evaluator = getExpressionEvaluator();
> +
> + // Iterate over the elements in 'source' and
>'fullSource' until a primary key match is found
> + value = findPrimaryKeyMatch(primaryKey, PARAMETER_SOURCE);
> + if (value == null)
> + value = findPrimaryKeyMatch(primaryKey,
>PARAMETER_FULL_SOURCE);
> +
> + return value;
> + }
> +
> + private Object findPrimaryKeyMatch(Object primaryKey, String parameter)
> + {
> + ExpressionEvaluator evaluator = getExpressionEvaluator();
> + String keyExpression = getKeyExpression();
> +
> + Map primaryKeys = getPrimaryKeyMap();
> + if (primaryKeys == null)
> + primaryKeys = new HashMap();
>
> - Iterator iteratorSource = (Iterator)
>getValueConverter().coerceValue(fullSource, Iterator.class);
> - while (iteratorSource.hasNext()) {
> - Object value = iteratorSource.next();
> - Object primaryKey = evaluator.read(value, keyExpression);
> - if (primaryKey != null)
> - primaryKeys.put(primaryKey, value);
> - }
> + Map sourceIteratorMap = getSourceIteratorMap();
> + if (sourceIteratorMap == null)
> + sourceIteratorMap = new HashMap();
>
> - setPrimaryKeyMap(primaryKeys);
> - return primaryKeys;
> + Iterator it = (Iterator) sourceIteratorMap.get(parameter);
> + if (it == null) {
> + it = getSource(parameter);
> + if (it == null)
> + it = Collections.EMPTY_LIST.iterator();
> + }
> +
> + try {
> + while (it.hasNext()) {
> + Object sourceValue = it.next();
> + Object sourcePrimaryKey =
>evaluator.read(sourceValue, keyExpression);
> + if (sourcePrimaryKey != null)
> + primaryKeys.put(sourcePrimaryKey, sourceValue);
> +
> + if (primaryKey.equals(sourcePrimaryKey)) {
> + return sourceValue;
> + }
> + }
> +
> + return null;
> + }
> + finally {
> + sourceIteratorMap.put(parameter, it);
> + setSourceIteratorMap(sourceIteratorMap);
> + setPrimaryKeyMap(primaryKeys);
> + }
> + }
> +
> + private void updateOutputParameters()
> + {
> + IBinding indexBinding = getBinding("index");
> + if (indexBinding != null)
> + indexBinding.setObject(new Integer(_index));
> +
> + IBinding valueBinding = getBinding("value");
> + if (valueBinding != null)
> + valueBinding.setObject(_value);
> }
>
> /**
>
>
>
> 1.3 +3 -3
>jakarta-tapestry/framework/src/java/org/apache/tapestry/components/For.jwc
>
> Index: For.jwc
> ===================================================================
> RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/components/For.jwc,v
> retrieving revision 1.2
> retrieving revision 1.3
> diff -u -r1.2 -r1.3
> --- For.jwc 28 Jul 2005 19:10:40 -0000 1.2
> +++ For.jwc 2 Aug 2005 21:39:56 -0000 1.3
> @@ -70,9 +70,9 @@
> <parameter name="fullSource">
> <description>
> Only active in a form and in combination with the
>'keyExpression' parameter.
> - The objects provided by this parameter will be used to
>determine the values
> - referred to by the primary keys stored in the form.
> - If this parameter is not bound, 'source' is used instead.
> + If an object corresponding to a primary key stored in the form cannot be
> + found in the 'source' parameter, then the objects provided by
>this parameter
> + are searched for a match next.
> </description>
> </parameter>
>
>
>
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
>For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
>
>
>
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
Re: Unused variables
Posted by Howard Lewis Ship <hl...@gmail.com>.
Good suggestion; I'm doing that, and correcting all the errors right now.
On 8/5/05, Markus Wiederkehr <ma...@gmail.com> wrote:
> You can easily share these settings in Eclipse.
>
> Open your project's properties dialog. Select "Java Compiler" ->
> "Errors/Warnings" and activate "Enable project specific settings".
>
> You might want to share some Java Code Styles, too.
>
> Regards,
> Markus
>
> On 8/3/05, Howard Lewis Ship <hl...@gmail.com> wrote:
> > Mindbridge,
> >
> > I think we have different settings for compiling under Eclipse.
> >
> > I have unused variables set as an error, so I had to change your
> > check-in to compile and run the test suite.
> >
> > I'm looking for a way we can share these settings.
> >
> > In addition we may need a discussion about what the setting should be.
> >
> > Especially under JDK 1.5, there are so many warnings that they no
> > longer mean anything, only errors will ever get noticed.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
>
>
--
Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator, Jakarta Tapestry
Creator, Jakarta HiveMind
Professional Tapestry training, mentoring, support
and project work. http://howardlewisship.com
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
Re: Unused variables
Posted by Markus Wiederkehr <ma...@gmail.com>.
You can easily share these settings in Eclipse.
Open your project's properties dialog. Select "Java Compiler" ->
"Errors/Warnings" and activate "Enable project specific settings".
You might want to share some Java Code Styles, too.
Regards,
Markus
On 8/3/05, Howard Lewis Ship <hl...@gmail.com> wrote:
> Mindbridge,
>
> I think we have different settings for compiling under Eclipse.
>
> I have unused variables set as an error, so I had to change your
> check-in to compile and run the test suite.
>
> I'm looking for a way we can share these settings.
>
> In addition we may need a discussion about what the setting should be.
>
> Especially under JDK 1.5, there are so many warnings that they no
> longer mean anything, only errors will ever get noticed.
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
Unused variables
Posted by Howard Lewis Ship <hl...@gmail.com>.
Mindbridge,
I think we have different settings for compiling under Eclipse.
I have unused variables set as an error, so I had to change your
check-in to compile and run the test suite.
I'm looking for a way we can share these settings.
In addition we may need a discussion about what the setting should be.
Especially under JDK 1.5, there are so many warnings that they no
longer mean anything, only errors will ever get noticed.
---------- Forwarded message ----------
From: mindbridge@apache.org <mi...@apache.org>
Date: 2 Aug 2005 21:39:56 -0000
Subject: cvs commit:
jakarta-tapestry/framework/src/java/org/apache/tapestry/components
ForBean.java For.jwc
To: jakarta-tapestry-cvs@apache.org
mindbridge 2005/08/02 14:39:56
Modified: framework/src/java/org/apache/tapestry/components
ForBean.java For.jwc
Log:
A more efficient version of the For component
Revision Changes Path
1.2 +235 -172
jakarta-tapestry/framework/src/java/org/apache/tapestry/components/ForBean.java
Index: ForBean.java
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/components/ForBean.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ForBean.java 4 Jul 2005 21:31:38 -0000 1.1
+++ ForBean.java 2 Aug 2005 21:39:56 -0000 1.2
@@ -16,6 +16,7 @@
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -39,6 +40,9 @@
public abstract class ForBean extends AbstractFormComponent {
private static final char DESC_VALUE = 'V';
private static final char DESC_PRIMARY_KEY = 'P';
+
+ private static final String PARAMETER_SOURCE = "source";
+ private static final String PARAMETER_FULL_SOURCE = "fullSource";
// parameters
public abstract Object getSource();
@@ -53,6 +57,8 @@
// properties
public abstract Map getPrimaryKeyMap();
public abstract void setPrimaryKeyMap(Map primaryKeys);
+ public abstract Map getSourceIteratorMap();
+ public abstract void setSourceIteratorMap(Map sourceIteratorMap);
// injects
public abstract DataSqueezer getDataSqueezer();
@@ -63,113 +69,7 @@
private Object _value;
private int _index;
private boolean _rendering;
-
- /**
- * Gets the source binding and returns an {@link Iterator}
- * representing
- * the values identified by the source. Returns an empty
{@link Iterator}
- * if the binding, or the binding value, is null.
- *
- * <p>Invokes {@link Tapestry#coerceToIterator(Object)} to perform
- * the actual conversion.
- *
- **/
-
- protected Iterator getSourceData()
- {
- Object source = getSource();
- if (source == null)
- return null;
-
- Iterator iteratorSource = (Iterator)
getValueConverter().coerceValue(source, Iterator.class);
-
- return iteratorSource;
- }
-
- protected Iterator storeSourceData(IForm form, String name)
- {
- Iterator iteratorSource = getSourceData();
- if (iteratorSource == null)
- return null;
-
- // extract primary keys from data
- StringBuffer pkDesc = new StringBuffer();
- List data = new ArrayList();
- List pks = new ArrayList();
- while (iteratorSource.hasNext()) {
- Object value = iteratorSource.next();
- data.add(value);
-
- Object pk = getPrimaryKeyFromValue(value);
- if (pk == null) {
- pk = value;
- pkDesc.append(DESC_VALUE);
- }
- else
- pkDesc.append(DESC_PRIMARY_KEY);
- pks.add(pk);
- }
-
- // store primary keys
- form.addHiddenValue(name, pkDesc.toString());
- for (Iterator it = pks.iterator(); it.hasNext();) {
- Object pk = it.next();
- try {
- String stringRep =
getDataSqueezer().squeeze(pk);
- form.addHiddenValue(name, stringRep);
- } catch (IOException ex) {
- throw new ApplicationRuntimeException(
- Tapestry.format("For.unable-to-convert-value", pk),
- this,
- null,
- ex);
- }
- }
- return data.iterator();
- }
-
- protected Iterator getStoredData(IRequestCycle cycle, String name)
- {
- String[] submittedPrimaryKeys = cycle.getParameters(name);
- String pkDesc = submittedPrimaryKeys[0];
-
- // unsqueeze data
- List data = new ArrayList(submittedPrimaryKeys.length-1);
- List pks = new ArrayList(submittedPrimaryKeys.length-1);
- for (int i = 1; i < submittedPrimaryKeys.length; i++) {
- String stringRep = submittedPrimaryKeys[i];
- try {
- Object value =
getDataSqueezer().unsqueeze(stringRep);
- data.add(value);
- if (i <= pkDesc.length() &&
pkDesc.charAt(i-1) == DESC_PRIMARY_KEY)
- pks.add(value);
- } catch (IOException ex) {
- throw new ApplicationRuntimeException(
-
Tapestry.format("For.unable-to-convert-string", stringRep),
- this,
- null,
- ex);
- }
- }
-
- // update the binding with the list of primary keys
- IBinding primaryKeysBinding = getBinding("primaryKeys");
- if (primaryKeysBinding != null)
- primaryKeysBinding.setObject(pks);
-
- // convert from primary keys to data
- for (int i = 0; i < data.size(); i++) {
- if (i <= pkDesc.length() && pkDesc.charAt(i) ==
DESC_PRIMARY_KEY) {
- Object pk = data.get(i);
- Object value = getValueFromPrimaryKey(pk);
- data.set(i, value);
- }
- }
-
- return data.iterator();
- }
-
/**
* Gets the source binding and iterates through
* its values. For each, it updates the value binding and
render's its wrapped elements.
@@ -187,21 +87,8 @@
if (cycleRewinding && form != null && !form.isRewinding())
return;
- boolean bInForm = (form != null && !getVolatile());
-
- String name = "";
- if (form != null)
- name = form.getElementId(this);
-
// Get the data to be iterated upon. Store in form if needed.
- Iterator dataSource;
- if (!bInForm)
- dataSource = getSourceData();
- else if (cycleRewinding)
- dataSource = getStoredData(cycle, name);
- else
- dataSource = storeSourceData(form, name);
-
+ Iterator dataSource = getData(cycle, form);
// Do not iterate if dataSource is null.
// The dataSource was either not convertable to Iterator,
or was empty.
@@ -222,13 +109,7 @@
_value = dataSource.next();
// Update output component parameters
- IBinding indexBinding = getBinding("index");
- if (indexBinding != null)
- indexBinding.setObject(new Integer(_index));
-
- IBinding valueBinding = getBinding("value");
- if (valueBinding != null)
- valueBinding.setObject(_value);
+ updateOutputParameters();
// Render component
if (element != null)
@@ -251,31 +132,160 @@
_value = null;
}
}
-
- private Object restoreValue(IForm form, String name, Object primaryKey)
+
+
+ /**
+ * Returns a list with the values to be iterated upon.
+ *
+ * The list is obtained in different ways:
+ * - If the component is not located in a form or 'volatile' is
set to true,
+ * then the simply the values passed to 'source' are returned
(same as Foreach)
+ * - If the component is in a form, and the form is rewinding,
the values stored
+ * in the form are returned -- rewind is then always the
same as render.
+ * - If the component is in a form, and the form is being
rendered, the values
+ * are stored in the form as Hidden fields.
+ *
+ * @param cycle The current request cycle
+ * @param form The form within which the component is located (if any)
+ * @return An iterator with the values to be cycled upon
+ **/
+ private Iterator getData(IRequestCycle cycle, IForm form) {
+ if (form == null || getVolatile())
+ return getSource(PARAMETER_SOURCE);
+
+ String name = form.getElementId(this);
+ if (cycle.isRewinding())
+ return getStoredData(cycle, name);
+ else
+ return storeSourceData(form, name);
+ }
+
+ /**
+ * Returns an {@link Iterator} containing the values provided
+ * by the identified source binding.
+ *
+ * @param parameter The name of the source binding
+ * @return an iterator with the bound values. null if the
parameter is not bound
+ * or the conversion cannot be performed
+ **/
+ protected Iterator getSource(String parameter)
+ {
+ IBinding binding = getBinding(parameter);
+ if (binding == null)
+ return null;
+
+ Object data = binding.getObject();
+ return (Iterator)
getValueConverter().coerceValue(data, Iterator.class);
+ }
+
+ /**
+ * Returns a list of the values stored as Hidden fields in the form.
+ * A conversion is performed if the primary key of the value is stored.
+ *
+ * @param cycle The current request cycle
+ * @param name The name of the HTTP parameter whether the values
+ * @return an iterator with the values stored in the provided
Hidden fields
+ **/
+ protected Iterator getStoredData(IRequestCycle cycle, String name)
{
- return getValueFromPrimaryKey(primaryKey);
+ String[] submittedPrimaryKeys = cycle.getParameters(name);
+ String pkDesc = submittedPrimaryKeys[0];
+
+ // unsqueeze data
+ List data = new ArrayList(submittedPrimaryKeys.length-1);
+ List pks = new ArrayList(submittedPrimaryKeys.length-1);
+ for (int i = 1; i < submittedPrimaryKeys.length; i++) {
+ String stringRep = submittedPrimaryKeys[i];
+ try {
+ Object value =
getDataSqueezer().unsqueeze(stringRep);
+ data.add(value);
+ if (i <= pkDesc.length() &&
pkDesc.charAt(i-1) == DESC_PRIMARY_KEY)
+ pks.add(value);
+ } catch (IOException ex) {
+ throw new ApplicationRuntimeException(
+
Tapestry.format("For.unable-to-convert-string", stringRep),
+ this,
+ null,
+ ex);
+ }
+ }
+
+ // update the binding with the list of primary keys
+ IBinding primaryKeysBinding = getBinding("primaryKeys");
+ if (primaryKeysBinding != null)
+ primaryKeysBinding.setObject(pks);
+
+ // convert from primary keys to data
+ for (int i = 0; i < data.size(); i++) {
+ if (i <= pkDesc.length() && pkDesc.charAt(i) ==
DESC_PRIMARY_KEY) {
+ Object pk = data.get(i);
+ Object value = getValueFromPrimaryKey(pk);
+ data.set(i, value);
+ }
+ }
+
+ return data.iterator();
}
- private void storeValue(IForm form, String name, Object value)
+ /**
+ * Stores the provided data in the form and then returns the
data as an iterator.
+ * If the primary key of the value can be determined,
+ * then that primary key is saved instead.
+ *
+ * @param form The form where the data will be stored
+ * @param name The name under which the data will be stored
+ * @return an iterator with the bound values stored in the form
+ **/
+ protected Iterator storeSourceData(IForm form, String name)
{
- Object convertedValue = getPrimaryKeyFromValue(value);
+ Iterator iteratorSource = getSource(PARAMETER_SOURCE);
+ if (iteratorSource == null)
+ return null;
- try
- {
- String externalValue =
getDataSqueezer().squeeze(convertedValue);
- form.addHiddenValue(name, externalValue);
- }
- catch (IOException ex)
- {
- throw new ApplicationRuntimeException(
- Tapestry.format("For.unable-to-convert-value", value),
- this,
- null,
- ex);
- }
+ // extract primary keys from data
+ StringBuffer pkDesc = new StringBuffer();
+ List data = new ArrayList();
+ List pks = new ArrayList();
+ while (iteratorSource.hasNext()) {
+ Object value = iteratorSource.next();
+ data.add(value);
+
+ Object pk = getPrimaryKeyFromValue(value);
+ if (pk == null) {
+ pk = value;
+ pkDesc.append(DESC_VALUE);
+ }
+ else
+ pkDesc.append(DESC_PRIMARY_KEY);
+ pks.add(pk);
+ }
+
+ // store primary keys
+ form.addHiddenValue(name, pkDesc.toString());
+ for (Iterator it = pks.iterator(); it.hasNext();) {
+ Object pk = it.next();
+ try {
+ String stringRep =
getDataSqueezer().squeeze(pk);
+ form.addHiddenValue(name, stringRep);
+ } catch (IOException ex) {
+ throw new ApplicationRuntimeException(
+ Tapestry.format("For.unable-to-convert-value", pk),
+ this,
+ null,
+ ex);
+ }
+ }
+
+ return data.iterator();
}
+ /**
+ * Returns the primary key of the given value.
+ * Uses the 'keyExpression' or the 'converter' (if either is provided).
+ *
+ * @param value The value from which the primary key should be extracted
+ * @return The primary key of the value, or null if such cannot
be extracted.
+ */
private Object getPrimaryKeyFromValue(Object value) {
Object primaryKey = null;
@@ -292,18 +302,20 @@
return primaryKey;
}
+ /**
+ * Returns a value that corresponds to the provided primary key.
+ * Uses either the 'keyExpression' if provided
+ *
+ * @param primaryKey
+ * @return
+ */
private Object getValueFromPrimaryKey(Object primaryKey) {
Object value = null;
- if (value == null && getKeyExpression() != null) {
- String keyExpression = getKeyExpression();
- if (keyExpression != null) {
- Map primaryKeys = getPrimaryKeyMap();
- if (primaryKeys == null)
- primaryKeys =
initializePrimaryKeysFromSource(keyExpression);
- value = primaryKeys.get(primaryKeys);
- }
- }
+ // if keyExpression is defined, try to get the object in that way
+ String keyExpression = getKeyExpression();
+ if (keyExpression != null)
+ value =
getValueFromExpressionPrimaryKeys(keyExpression, primaryKey);
if (value == null) {
IPrimaryKeyConverter converter = getConverter();
@@ -317,28 +329,79 @@
return value;
}
- private Map initializePrimaryKeysFromSource(String keyExpression)
+ private Object getValueFromExpressionPrimaryKeys(String
keyExpression, Object primaryKey)
{
- Map primaryKeys = new HashMap();
-
- Object fullSource = getFullSource();
- if (fullSource == null)
- fullSource = getSource();
- if (fullSource == null)
- return primaryKeys;
+ Object value = null;
- ExpressionEvaluator evaluator = getExpressionEvaluator();
+ Map primaryKeys = getPrimaryKeyMap();
+ if (primaryKeys == null)
+ primaryKeys = new HashMap();
+ else {
+ value = primaryKeys.get(primaryKey);
+ if (value != null)
+ return value;
+ }
+
+ ExpressionEvaluator evaluator = getExpressionEvaluator();
+
+ // Iterate over the elements in 'source' and
'fullSource' until a primary key match is found
+ value = findPrimaryKeyMatch(primaryKey, PARAMETER_SOURCE);
+ if (value == null)
+ value = findPrimaryKeyMatch(primaryKey,
PARAMETER_FULL_SOURCE);
+
+ return value;
+ }
+
+ private Object findPrimaryKeyMatch(Object primaryKey, String parameter)
+ {
+ ExpressionEvaluator evaluator = getExpressionEvaluator();
+ String keyExpression = getKeyExpression();
+
+ Map primaryKeys = getPrimaryKeyMap();
+ if (primaryKeys == null)
+ primaryKeys = new HashMap();
- Iterator iteratorSource = (Iterator)
getValueConverter().coerceValue(fullSource, Iterator.class);
- while (iteratorSource.hasNext()) {
- Object value = iteratorSource.next();
- Object primaryKey = evaluator.read(value, keyExpression);
- if (primaryKey != null)
- primaryKeys.put(primaryKey, value);
- }
+ Map sourceIteratorMap = getSourceIteratorMap();
+ if (sourceIteratorMap == null)
+ sourceIteratorMap = new HashMap();
- setPrimaryKeyMap(primaryKeys);
- return primaryKeys;
+ Iterator it = (Iterator) sourceIteratorMap.get(parameter);
+ if (it == null) {
+ it = getSource(parameter);
+ if (it == null)
+ it = Collections.EMPTY_LIST.iterator();
+ }
+
+ try {
+ while (it.hasNext()) {
+ Object sourceValue = it.next();
+ Object sourcePrimaryKey =
evaluator.read(sourceValue, keyExpression);
+ if (sourcePrimaryKey != null)
+ primaryKeys.put(sourcePrimaryKey, sourceValue);
+
+ if (primaryKey.equals(sourcePrimaryKey)) {
+ return sourceValue;
+ }
+ }
+
+ return null;
+ }
+ finally {
+ sourceIteratorMap.put(parameter, it);
+ setSourceIteratorMap(sourceIteratorMap);
+ setPrimaryKeyMap(primaryKeys);
+ }
+ }
+
+ private void updateOutputParameters()
+ {
+ IBinding indexBinding = getBinding("index");
+ if (indexBinding != null)
+ indexBinding.setObject(new Integer(_index));
+
+ IBinding valueBinding = getBinding("value");
+ if (valueBinding != null)
+ valueBinding.setObject(_value);
}
/**
1.3 +3 -3
jakarta-tapestry/framework/src/java/org/apache/tapestry/components/For.jwc
Index: For.jwc
===================================================================
RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/components/For.jwc,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- For.jwc 28 Jul 2005 19:10:40 -0000 1.2
+++ For.jwc 2 Aug 2005 21:39:56 -0000 1.3
@@ -70,9 +70,9 @@
<parameter name="fullSource">
<description>
Only active in a form and in combination with the
'keyExpression' parameter.
- The objects provided by this parameter will be used to
determine the values
- referred to by the primary keys stored in the form.
- If this parameter is not bound, 'source' is used instead.
+ If an object corresponding to a primary key stored in the form cannot be
+ found in the 'source' parameter, then the objects provided by
this parameter
+ are searched for a match next.
</description>
</parameter>
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
--
Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator, Jakarta Tapestry
Creator, Jakarta HiveMind
Professional Tapestry training, mentoring, support
and project work. http://howardlewisship.com
---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org