1 |
| |
2 |
| |
3 |
| |
4 |
| |
5 |
| |
6 |
| |
7 |
| |
8 |
| |
9 |
| |
10 |
| |
11 |
| |
12 |
| |
13 |
| |
14 |
| |
15 |
| package org.apache.tapestry.components; |
16 |
| |
17 |
| import java.util.ArrayList; |
18 |
| import java.util.Collections; |
19 |
| import java.util.HashMap; |
20 |
| import java.util.Iterator; |
21 |
| import java.util.List; |
22 |
| import java.util.Map; |
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 |
| |
38 |
| |
39 |
| public abstract class ForBean extends AbstractFormComponent |
40 |
| { |
41 |
| private static final char DESC_VALUE = 'V'; |
42 |
| |
43 |
| private static final char DESC_PRIMARY_KEY = 'P'; |
44 |
| |
45 |
| private static final String PARAMETER_SOURCE = "source"; |
46 |
| |
47 |
| private static final String PARAMETER_FULL_SOURCE = "fullSource"; |
48 |
| |
49 |
| |
50 |
| public abstract Object getSource(); |
51 |
| |
52 |
| public abstract Object getFullSource(); |
53 |
| |
54 |
| public abstract String getElement(); |
55 |
| |
56 |
| public abstract boolean getVolatile(); |
57 |
| |
58 |
| public abstract Object getDefaultValue(); |
59 |
| |
60 |
| public abstract String getPrimaryKey(); |
61 |
| |
62 |
| public abstract IPrimaryKeyConverter getConverter(); |
63 |
| |
64 |
| public abstract String getKeyExpression(); |
65 |
| |
66 |
| |
67 |
| public abstract Map getPrimaryKeyMap(); |
68 |
| |
69 |
| public abstract void setPrimaryKeyMap(Map primaryKeys); |
70 |
| |
71 |
| public abstract Map getSourceIteratorMap(); |
72 |
| |
73 |
| public abstract void setSourceIteratorMap(Map sourceIteratorMap); |
74 |
| |
75 |
| |
76 |
| public abstract DataSqueezer getDataSqueezer(); |
77 |
| |
78 |
| public abstract ValueConverter getValueConverter(); |
79 |
| |
80 |
| public abstract ExpressionEvaluator getExpressionEvaluator(); |
81 |
| |
82 |
| private Object _value; |
83 |
| |
84 |
| private int _index; |
85 |
| |
86 |
| private boolean _rendering; |
87 |
| |
88 |
| |
89 |
| |
90 |
| |
91 |
| |
92 |
| |
93 |
15
| protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
|
94 |
| { |
95 |
| |
96 |
15
| IForm form = (IForm) cycle.getAttribute(TapestryUtils.FORM_ATTRIBUTE);
|
97 |
| |
98 |
| |
99 |
| |
100 |
15
| boolean cycleRewinding = cycle.isRewinding();
|
101 |
15
| if (cycleRewinding && form != null && !form.isRewinding())
|
102 |
0
| return;
|
103 |
| |
104 |
| |
105 |
15
| Iterator dataSource = getData(cycle, form);
|
106 |
| |
107 |
| |
108 |
| |
109 |
15
| if (dataSource == null)
|
110 |
0
| return;
|
111 |
| |
112 |
15
| String element = getElement();
|
113 |
| |
114 |
| |
115 |
15
| try
|
116 |
| { |
117 |
15
| _index = 0;
|
118 |
15
| _rendering = true;
|
119 |
| |
120 |
15
| while (dataSource.hasNext())
|
121 |
| { |
122 |
| |
123 |
34
| _value = dataSource.next();
|
124 |
| |
125 |
| |
126 |
34
| updateOutputParameters();
|
127 |
| |
128 |
| |
129 |
34
| if (element != null)
|
130 |
| { |
131 |
12
| writer.begin(element);
|
132 |
12
| renderInformalParameters(writer, cycle);
|
133 |
| } |
134 |
| |
135 |
34
| renderBody(writer, cycle);
|
136 |
| |
137 |
34
| if (element != null)
|
138 |
12
| writer.end();
|
139 |
| |
140 |
34
| _index++;
|
141 |
| } |
142 |
| } |
143 |
| finally |
144 |
| { |
145 |
15
| _rendering = false;
|
146 |
15
| _value = null;
|
147 |
| } |
148 |
| } |
149 |
| |
150 |
| |
151 |
| |
152 |
| |
153 |
| |
154 |
| |
155 |
| |
156 |
| |
157 |
| |
158 |
| |
159 |
| |
160 |
| |
161 |
| |
162 |
| |
163 |
| |
164 |
15
| private Iterator getData(IRequestCycle cycle, IForm form)
|
165 |
| { |
166 |
15
| if (form == null || getVolatile())
|
167 |
6
| return getSource(PARAMETER_SOURCE);
|
168 |
| |
169 |
9
| String name = form.getElementId(this);
|
170 |
9
| if (cycle.isRewinding())
|
171 |
3
| return getStoredData(cycle, name);
|
172 |
| |
173 |
6
| return storeSourceData(form, name);
|
174 |
| } |
175 |
| |
176 |
| |
177 |
| |
178 |
| |
179 |
| |
180 |
| |
181 |
| |
182 |
| |
183 |
| |
184 |
16
| protected Iterator getSource(String parameter)
|
185 |
| { |
186 |
16
| IBinding binding = getBinding(parameter);
|
187 |
16
| if (binding == null)
|
188 |
1
| return null;
|
189 |
| |
190 |
15
| Object data = binding.getObject();
|
191 |
15
| return (Iterator) getValueConverter().coerceValue(data, Iterator.class);
|
192 |
| } |
193 |
| |
194 |
| |
195 |
| |
196 |
| |
197 |
| |
198 |
| |
199 |
| |
200 |
| |
201 |
| |
202 |
| |
203 |
| |
204 |
3
| protected Iterator getStoredData(IRequestCycle cycle, String name)
|
205 |
| { |
206 |
3
| String[] submittedPrimaryKeys = cycle.getParameters(name);
|
207 |
3
| String pkDesc = submittedPrimaryKeys[0];
|
208 |
| |
209 |
| |
210 |
3
| List data = new ArrayList(submittedPrimaryKeys.length - 1);
|
211 |
3
| List pks = new ArrayList(submittedPrimaryKeys.length - 1);
|
212 |
3
| for (int i = 1; i < submittedPrimaryKeys.length; i++)
|
213 |
| { |
214 |
6
| String stringRep = submittedPrimaryKeys[i];
|
215 |
6
| try
|
216 |
| { |
217 |
6
| Object value = getDataSqueezer().unsqueeze(stringRep);
|
218 |
6
| data.add(value);
|
219 |
6
| if (i <= pkDesc.length() && pkDesc.charAt(i - 1) == DESC_PRIMARY_KEY)
|
220 |
4
| pks.add(value);
|
221 |
| } |
222 |
| catch (Exception ex) |
223 |
| { |
224 |
0
| throw new ApplicationRuntimeException(Tapestry.format(
|
225 |
| "For.unable-to-convert-string", |
226 |
| stringRep), this, null, ex); |
227 |
| } |
228 |
| } |
229 |
| |
230 |
| |
231 |
3
| IBinding primaryKeysBinding = getBinding("primaryKeys");
|
232 |
3
| if (primaryKeysBinding != null)
|
233 |
0
| primaryKeysBinding.setObject(pks);
|
234 |
| |
235 |
| |
236 |
3
| for (int i = 0; i < data.size(); i++)
|
237 |
| { |
238 |
6
| if (i <= pkDesc.length() && pkDesc.charAt(i) == DESC_PRIMARY_KEY)
|
239 |
| { |
240 |
4
| Object pk = data.get(i);
|
241 |
4
| Object value = getValueFromPrimaryKey(pk);
|
242 |
4
| data.set(i, value);
|
243 |
| } |
244 |
| } |
245 |
| |
246 |
3
| return data.iterator();
|
247 |
| } |
248 |
| |
249 |
| |
250 |
| |
251 |
| |
252 |
| |
253 |
| |
254 |
| |
255 |
| |
256 |
| |
257 |
| |
258 |
| |
259 |
6
| protected Iterator storeSourceData(IForm form, String name)
|
260 |
| { |
261 |
6
| Iterator iteratorSource = getSource(PARAMETER_SOURCE);
|
262 |
6
| if (iteratorSource == null)
|
263 |
0
| return null;
|
264 |
| |
265 |
| |
266 |
6
| StringBuffer pkDesc = new StringBuffer();
|
267 |
6
| List data = new ArrayList();
|
268 |
6
| List pks = new ArrayList();
|
269 |
6
| while (iteratorSource.hasNext())
|
270 |
| { |
271 |
12
| Object value = iteratorSource.next();
|
272 |
12
| data.add(value);
|
273 |
| |
274 |
12
| Object pk = getPrimaryKeyFromValue(value);
|
275 |
12
| if (pk == null)
|
276 |
| { |
277 |
4
| pk = value;
|
278 |
4
| pkDesc.append(DESC_VALUE);
|
279 |
| } |
280 |
| else |
281 |
8
| pkDesc.append(DESC_PRIMARY_KEY);
|
282 |
12
| pks.add(pk);
|
283 |
| } |
284 |
| |
285 |
| |
286 |
6
| form.addHiddenValue(name, pkDesc.toString());
|
287 |
6
| for (Iterator it = pks.iterator(); it.hasNext();)
|
288 |
| { |
289 |
12
| Object pk = it.next();
|
290 |
12
| try
|
291 |
| { |
292 |
12
| String stringRep = getDataSqueezer().squeeze(pk);
|
293 |
12
| form.addHiddenValue(name, stringRep);
|
294 |
| } |
295 |
| catch (Exception ex) |
296 |
| { |
297 |
0
| throw new ApplicationRuntimeException(Tapestry.format(
|
298 |
| "For.unable-to-convert-value", |
299 |
| pk), this, null, ex); |
300 |
| } |
301 |
| } |
302 |
| |
303 |
6
| return data.iterator();
|
304 |
| } |
305 |
| |
306 |
| |
307 |
| |
308 |
| |
309 |
| |
310 |
| |
311 |
| |
312 |
| |
313 |
| |
314 |
12
| private Object getPrimaryKeyFromValue(Object value)
|
315 |
| { |
316 |
12
| Object primaryKey = null;
|
317 |
| |
318 |
12
| String keyExpression = getKeyExpression();
|
319 |
12
| if (keyExpression != null)
|
320 |
8
| primaryKey = getExpressionEvaluator().read(value, keyExpression);
|
321 |
| |
322 |
12
| if (primaryKey == null)
|
323 |
| { |
324 |
4
| IPrimaryKeyConverter converter = getConverter();
|
325 |
4
| if (converter != null)
|
326 |
0
| primaryKey = converter.getPrimaryKey(value);
|
327 |
| } |
328 |
| |
329 |
12
| return primaryKey;
|
330 |
| } |
331 |
| |
332 |
| |
333 |
| |
334 |
| |
335 |
| |
336 |
| |
337 |
| |
338 |
| |
339 |
4
| private Object getValueFromPrimaryKey(Object primaryKey)
|
340 |
| { |
341 |
4
| Object value = null;
|
342 |
| |
343 |
| |
344 |
4
| String keyExpression = getKeyExpression();
|
345 |
4
| if (keyExpression != null)
|
346 |
4
| value = getValueFromExpressionPrimaryKeys(keyExpression, primaryKey);
|
347 |
| |
348 |
4
| if (value == null)
|
349 |
| { |
350 |
1
| IPrimaryKeyConverter converter = getConverter();
|
351 |
1
| if (converter != null)
|
352 |
0
| value = converter.getValue(primaryKey);
|
353 |
| } |
354 |
| |
355 |
4
| if (value == null)
|
356 |
1
| value = getDefaultValue();
|
357 |
| |
358 |
4
| return value;
|
359 |
| } |
360 |
| |
361 |
4
| private Object getValueFromExpressionPrimaryKeys(String keyExpression, Object primaryKey)
|
362 |
| { |
363 |
4
| Object value = null;
|
364 |
| |
365 |
4
| Map primaryKeys = getPrimaryKeyMap();
|
366 |
4
| if (primaryKeys == null)
|
367 |
2
| primaryKeys = new HashMap();
|
368 |
| else |
369 |
| { |
370 |
2
| value = primaryKeys.get(primaryKey);
|
371 |
2
| if (value != null)
|
372 |
1
| return value;
|
373 |
| } |
374 |
| |
375 |
| |
376 |
3
| value = findPrimaryKeyMatch(primaryKey, PARAMETER_SOURCE);
|
377 |
3
| if (value == null)
|
378 |
2
| value = findPrimaryKeyMatch(primaryKey, PARAMETER_FULL_SOURCE);
|
379 |
| |
380 |
3
| return value;
|
381 |
| } |
382 |
| |
383 |
5
| private Object findPrimaryKeyMatch(Object primaryKey, String parameter)
|
384 |
| { |
385 |
5
| ExpressionEvaluator evaluator = getExpressionEvaluator();
|
386 |
5
| String keyExpression = getKeyExpression();
|
387 |
| |
388 |
5
| Map primaryKeys = getPrimaryKeyMap();
|
389 |
5
| if (primaryKeys == null)
|
390 |
2
| primaryKeys = new HashMap();
|
391 |
| |
392 |
5
| Map sourceIteratorMap = getSourceIteratorMap();
|
393 |
5
| if (sourceIteratorMap == null)
|
394 |
2
| sourceIteratorMap = new HashMap();
|
395 |
| |
396 |
5
| Iterator it = (Iterator) sourceIteratorMap.get(parameter);
|
397 |
5
| if (it == null)
|
398 |
| { |
399 |
4
| it = getSource(parameter);
|
400 |
4
| if (it == null)
|
401 |
1
| it = Collections.EMPTY_LIST.iterator();
|
402 |
| } |
403 |
| |
404 |
5
| try
|
405 |
| { |
406 |
5
| while (it.hasNext())
|
407 |
| { |
408 |
42
| Object sourceValue = it.next();
|
409 |
42
| Object sourcePrimaryKey = evaluator.read(sourceValue, keyExpression);
|
410 |
42
| if (sourcePrimaryKey != null)
|
411 |
42
| primaryKeys.put(sourcePrimaryKey, sourceValue);
|
412 |
| |
413 |
42
| if (primaryKey.equals(sourcePrimaryKey))
|
414 |
| { |
415 |
2
| return sourceValue;
|
416 |
| } |
417 |
| } |
418 |
| |
419 |
3
| return null;
|
420 |
| } |
421 |
| finally |
422 |
| { |
423 |
5
| sourceIteratorMap.put(parameter, it);
|
424 |
5
| setSourceIteratorMap(sourceIteratorMap);
|
425 |
5
| setPrimaryKeyMap(primaryKeys);
|
426 |
| } |
427 |
| } |
428 |
| |
429 |
34
| private void updateOutputParameters()
|
430 |
| { |
431 |
34
| IBinding indexBinding = getBinding("index");
|
432 |
34
| if (indexBinding != null)
|
433 |
18
| indexBinding.setObject(new Integer(_index));
|
434 |
| |
435 |
34
| IBinding valueBinding = getBinding("value");
|
436 |
34
| if (valueBinding != null)
|
437 |
18
| valueBinding.setObject(_value);
|
438 |
| } |
439 |
| |
440 |
| |
441 |
| |
442 |
| |
443 |
| |
444 |
| |
445 |
| |
446 |
| |
447 |
28
| public final Object getValue()
|
448 |
| { |
449 |
28
| if (!_rendering)
|
450 |
0
| throw Tapestry.createRenderOnlyPropertyException(this, "value");
|
451 |
| |
452 |
28
| return _value;
|
453 |
| } |
454 |
| |
455 |
| |
456 |
| |
457 |
| |
458 |
| |
459 |
| |
460 |
| |
461 |
| |
462 |
| |
463 |
28
| public int getIndex()
|
464 |
| { |
465 |
28
| if (!_rendering)
|
466 |
0
| throw Tapestry.createRenderOnlyPropertyException(this, "index");
|
467 |
| |
468 |
28
| return _index;
|
469 |
| } |
470 |
| |
471 |
0
| public boolean isDisabled()
|
472 |
| { |
473 |
0
| return false;
|
474 |
| } |
475 |
| |
476 |
| |
477 |
0
| protected void renderFormComponent(IMarkupWriter writer, IRequestCycle cycle)
|
478 |
| { |
479 |
| } |
480 |
| |
481 |
0
| protected void rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle)
|
482 |
| { |
483 |
| } |
484 |
| } |