KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > components > ForBean


1 // Copyright 2004, 2005 The Apache Software Foundation
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15 package org.apache.tapestry.components;
16
17 import java.io.IOException JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23
24 import org.apache.hivemind.ApplicationRuntimeException;
25 import org.apache.tapestry.IBinding;
26 import org.apache.tapestry.IForm;
27 import org.apache.tapestry.IMarkupWriter;
28 import org.apache.tapestry.IRequestCycle;
29 import org.apache.tapestry.Tapestry;
30 import org.apache.tapestry.TapestryUtils;
31 import org.apache.tapestry.coerce.ValueConverter;
32 import org.apache.tapestry.form.AbstractFormComponent;
33 import org.apache.tapestry.services.DataSqueezer;
34 import org.apache.tapestry.services.ExpressionEvaluator;
35
36 /**
37  * @author mb
38  */

39 public abstract class ForBean extends AbstractFormComponent {
40     private static final char DESC_VALUE = 'V';
41     private static final char DESC_PRIMARY_KEY = 'P';
42
43     // parameters
44
public abstract Object JavaDoc getSource();
45     public abstract Object JavaDoc getFullSource();
46     public abstract String JavaDoc getElement();
47     public abstract boolean getVolatile();
48     public abstract Object JavaDoc getDefaultValue();
49     public abstract String JavaDoc getPrimaryKey();
50     public abstract IPrimaryKeyConverter getConverter();
51     public abstract String JavaDoc getKeyExpression();
52
53     // properties
54
public abstract Map JavaDoc getPrimaryKeyMap();
55     public abstract void setPrimaryKeyMap(Map JavaDoc primaryKeys);
56     
57     // injects
58
public abstract DataSqueezer getDataSqueezer();
59     public abstract ValueConverter getValueConverter();
60     public abstract ExpressionEvaluator getExpressionEvaluator();
61     
62     
63     private Object JavaDoc _value;
64     private int _index;
65     private boolean _rendering;
66     
67     /**
68      * Gets the source binding and returns an {@link Iterator}
69      * representing
70      * the values identified by the source. Returns an empty {@link Iterator}
71      * if the binding, or the binding value, is null.
72      *
73      * <p>Invokes {@link Tapestry#coerceToIterator(Object)} to perform
74      * the actual conversion.
75      *
76      **/

77
78     protected Iterator JavaDoc getSourceData()
79     {
80         Object JavaDoc source = getSource();
81         if (source == null)
82             return null;
83     
84         Iterator JavaDoc iteratorSource = (Iterator JavaDoc) getValueConverter().coerceValue(source, Iterator JavaDoc.class);
85         
86         return iteratorSource;
87     }
88
89     protected Iterator JavaDoc storeSourceData(IForm form, String JavaDoc name)
90     {
91         Iterator JavaDoc iteratorSource = getSourceData();
92         if (iteratorSource == null)
93             return null;
94         
95         // extract primary keys from data
96
StringBuffer JavaDoc pkDesc = new StringBuffer JavaDoc();
97         List JavaDoc data = new ArrayList JavaDoc();
98         List JavaDoc pks = new ArrayList JavaDoc();
99         while (iteratorSource.hasNext()) {
100             Object JavaDoc value = iteratorSource.next();
101             data.add(value);
102             
103             Object JavaDoc pk = getPrimaryKeyFromValue(value);
104             if (pk == null) {
105                 pk = value;
106                 pkDesc.append(DESC_VALUE);
107             }
108             else
109                 pkDesc.append(DESC_PRIMARY_KEY);
110             pks.add(pk);
111         }
112         
113         // store primary keys
114
form.addHiddenValue(name, pkDesc.toString());
115         for (Iterator JavaDoc it = pks.iterator(); it.hasNext();) {
116             Object JavaDoc pk = it.next();
117             try {
118                 String JavaDoc stringRep = getDataSqueezer().squeeze(pk);
119                 form.addHiddenValue(name, stringRep);
120             } catch (IOException JavaDoc ex) {
121                 throw new ApplicationRuntimeException(
122                         Tapestry.format("For.unable-to-convert-value", pk),
123                         this,
124                         null,
125                         ex);
126             }
127         }
128
129         return data.iterator();
130     }
131
132     protected Iterator JavaDoc getStoredData(IRequestCycle cycle, String JavaDoc name)
133     {
134         String JavaDoc[] submittedPrimaryKeys = cycle.getParameters(name);
135         String JavaDoc pkDesc = submittedPrimaryKeys[0];
136
137         // unsqueeze data
138
List JavaDoc data = new ArrayList JavaDoc(submittedPrimaryKeys.length-1);
139         List JavaDoc pks = new ArrayList JavaDoc(submittedPrimaryKeys.length-1);
140         for (int i = 1; i < submittedPrimaryKeys.length; i++) {
141             String JavaDoc stringRep = submittedPrimaryKeys[i];
142             try {
143                 Object JavaDoc value = getDataSqueezer().unsqueeze(stringRep);
144                 data.add(value);
145                 if (i <= pkDesc.length() && pkDesc.charAt(i-1) == DESC_PRIMARY_KEY)
146                     pks.add(value);
147             } catch (IOException JavaDoc ex) {
148                 throw new ApplicationRuntimeException(
149                         Tapestry.format("For.unable-to-convert-string", stringRep),
150                         this,
151                         null,
152                         ex);
153             }
154         }
155
156         // update the binding with the list of primary keys
157
IBinding primaryKeysBinding = getBinding("primaryKeys");
158         if (primaryKeysBinding != null)
159             primaryKeysBinding.setObject(pks);
160         
161         // convert from primary keys to data
162
for (int i = 0; i < data.size(); i++) {
163             if (i <= pkDesc.length() && pkDesc.charAt(i) == DESC_PRIMARY_KEY) {
164                 Object JavaDoc pk = data.get(i);
165                 Object JavaDoc value = getValueFromPrimaryKey(pk);
166                 data.set(i, value);
167             }
168         }
169         
170         return data.iterator();
171     }
172     
173     /**
174      * Gets the source binding and iterates through
175      * its values. For each, it updates the value binding and render's its wrapped elements.
176      *
177      **/

178
179     protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
180     {
181         // form may be null if component is not located in a form
182
IForm form = (IForm) cycle.getAttribute(TapestryUtils.FORM_ATTRIBUTE);
183
184         // If the cycle is rewinding, but not this particular form,
185
// then do nothing (don't even render the body).
186
boolean cycleRewinding = cycle.isRewinding();
187         if (cycleRewinding && form != null && !form.isRewinding())
188             return;
189
190         boolean bInForm = (form != null && !getVolatile());
191         
192         String JavaDoc name = "";
193         if (form != null)
194             name = form.getElementId(this);
195
196         // Get the data to be iterated upon. Store in form if needed.
197
Iterator JavaDoc dataSource;
198         if (!bInForm)
199             dataSource = getSourceData();
200         else if (cycleRewinding)
201             dataSource = getStoredData(cycle, name);
202         else
203             dataSource = storeSourceData(form, name);
204         
205         
206         // Do not iterate if dataSource is null.
207
// The dataSource was either not convertable to Iterator, or was empty.
208
if (dataSource == null)
209             return;
210
211         String JavaDoc element = getElement();
212
213         // Perform the iterations
214
try
215         {
216             _index = 0;
217             _rendering = true;
218
219             while (dataSource.hasNext())
220             {
221                 // Get current value
222
_value = dataSource.next();
223
224                 // Update output component parameters
225
IBinding indexBinding = getBinding("index");
226                 if (indexBinding != null)
227                     indexBinding.setObject(new Integer JavaDoc(_index));
228
229                 IBinding valueBinding = getBinding("value");
230                 if (valueBinding != null)
231                     valueBinding.setObject(_value);
232                 
233                 // Render component
234
if (element != null)
235                 {
236                     writer.begin(element);
237                     renderInformalParameters(writer, cycle);
238                 }
239
240                 renderBody(writer, cycle);
241
242                 if (element != null)
243                     writer.end();
244
245                 _index++;
246             }
247         }
248         finally
249         {
250             _rendering = false;
251             _value = null;
252         }
253     }
254
255     private Object JavaDoc restoreValue(IForm form, String JavaDoc name, Object JavaDoc primaryKey)
256     {
257         return getValueFromPrimaryKey(primaryKey);
258     }
259     
260     private void storeValue(IForm form, String JavaDoc name, Object JavaDoc value)
261     {
262         Object JavaDoc convertedValue = getPrimaryKeyFromValue(value);
263         
264         try
265         {
266             String JavaDoc externalValue = getDataSqueezer().squeeze(convertedValue);
267             form.addHiddenValue(name, externalValue);
268         }
269         catch (IOException JavaDoc ex)
270         {
271             throw new ApplicationRuntimeException(
272                 Tapestry.format("For.unable-to-convert-value", value),
273                 this,
274                 null,
275                 ex);
276         }
277     }
278
279     private Object JavaDoc getPrimaryKeyFromValue(Object JavaDoc value) {
280         Object JavaDoc primaryKey = null;
281         
282         String JavaDoc keyExpression = getKeyExpression();
283         if (keyExpression != null)
284             primaryKey = getExpressionEvaluator().read(value, keyExpression);
285     
286         if (primaryKey == null) {
287             IPrimaryKeyConverter converter = getConverter();
288             if (converter != null)
289                 primaryKey = converter.getPrimaryKey(value);
290         }
291
292         return primaryKey;
293     }
294     
295     private Object JavaDoc getValueFromPrimaryKey(Object JavaDoc primaryKey) {
296         Object JavaDoc value = null;
297
298         if (value == null && getKeyExpression() != null) {
299             String JavaDoc keyExpression = getKeyExpression();
300             if (keyExpression != null) {
301                 Map JavaDoc primaryKeys = getPrimaryKeyMap();
302                 if (primaryKeys == null)
303                     primaryKeys = initializePrimaryKeysFromSource(keyExpression);
304                 value = primaryKeys.get(primaryKeys);
305             }
306         }
307         
308         if (value == null) {
309             IPrimaryKeyConverter converter = getConverter();
310             if (converter != null)
311                 value = converter.getValue(primaryKey);
312         }
313
314         if (value == null)
315             value = getDefaultValue();
316
317         return value;
318     }
319     
320     private Map JavaDoc initializePrimaryKeysFromSource(String JavaDoc keyExpression)
321     {
322         Map JavaDoc primaryKeys = new HashMap JavaDoc();
323         
324         Object JavaDoc fullSource = getFullSource();
325         if (fullSource == null)
326             fullSource = getSource();
327         if (fullSource == null)
328             return primaryKeys;
329         
330         ExpressionEvaluator evaluator = getExpressionEvaluator();
331         
332         Iterator JavaDoc iteratorSource = (Iterator JavaDoc) getValueConverter().coerceValue(fullSource, Iterator JavaDoc.class);
333         while (iteratorSource.hasNext()) {
334             Object JavaDoc value = iteratorSource.next();
335             Object JavaDoc primaryKey = evaluator.read(value, keyExpression);
336             if (primaryKey != null)
337                 primaryKeys.put(primaryKey, value);
338         }
339         
340         setPrimaryKeyMap(primaryKeys);
341         return primaryKeys;
342     }
343     
344     /**
345      * Returns the most recent value extracted from the source parameter.
346      *
347      * @throws org.apache.tapestry.ApplicationRuntimeException if the Foreach is not currently rendering.
348      *
349      **/

350
351     public final Object JavaDoc getValue()
352     {
353         if (!_rendering)
354             throw Tapestry.createRenderOnlyPropertyException(this, "value");
355   
356         return _value;
357     }
358
359     /**
360      * The index number, within the {@link #getSource() source}, of the
361      * the current value.
362      *
363      * @throws org.apache.tapestry.ApplicationRuntimeException if the Foreach is not currently rendering.
364      *
365      * @since 2.2
366      *
367      **/

368     
369     public int getIndex()
370     {
371         if (!_rendering)
372             throw Tapestry.createRenderOnlyPropertyException(this, "index");
373         
374         return _index;
375     }
376
377     public boolean isDisabled()
378     {
379         return false;
380     }
381
382     // Do nothing in those methods, but make the JVM happy
383
protected void renderFormComponent(IMarkupWriter writer, IRequestCycle cycle) { }
384     protected void rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle) { }
385 }
386
Popular Tags