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