1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.equanda.tapestry5.components;
26
27 import org.apache.tapestry5.*;
28 import org.apache.tapestry5.annotations.*;
29 import org.apache.tapestry5.corelib.components.Delegate;
30 import org.apache.tapestry5.corelib.components.Loop;
31 import org.apache.tapestry5.ioc.annotations.Inject;
32 import org.apache.tapestry5.services.ComponentDefaultProvider;
33 import org.apache.tapestry5.services.Environment;
34 import org.apache.tapestry5.services.FormSupport;
35 import org.apache.tapestry5.services.Request;
36 import org.chenillekit.tapestry.core.components.Hidden;
37 import org.equanda.tapestry5.base.ObjectCreatorDelegate;
38 import org.equanda.tapestry5.base.PagerConfig;
39 import org.slf4j.Logger;
40
41 import java.util.ArrayList;
42 import java.util.Collection;
43 import java.util.List;
44
45
46
47
48
49
50 public class JSPagedLoop
51 implements ClientElement
52 {
53 @Environmental
54 private RenderSupport renderSupport;
55
56 @Inject
57 private Environment environment;
58
59 @Inject
60 private Logger log;
61
62 @Inject
63 private ComponentResources resources;
64
65 @Environmental
66 private FormSupport formSupport;
67
68 @Inject
69 private Request request;
70
71 @Inject
72 private ComponentDefaultProvider componentDefaultProvider;
73
74 @Parameter( value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL )
75 private String clientId;
76
77
78
79
80
81 @Parameter( value = "prop:componentResources.elementName", defaultPrefix = BindingConstants.LITERAL )
82 private String elementName;
83
84
85 @Parameter( required = true, principal = true )
86 private Collection<Object> source;
87
88 @Persist
89 private List<Object> addedRowsList;
90
91 @Persist
92 private List<Object> pagedSource;
93
94
95
96
97
98 @Parameter( "25" )
99 private int rowsPerPage;
100
101 @Persist
102 private int currentPage;
103
104 private int addedRowCount;
105
106
107 @Parameter
108 private Object value;
109
110 @Parameter( defaultPrefix = BindingConstants.PROP )
111 private ObjectCreatorDelegate objectCreatorDelegate;
112
113
114 @Parameter
115 private int index;
116
117 @Parameter
118 private int additionalRowCount;
119
120
121
122
123
124 @Parameter
125 private PrimaryKeyEncoder<?, ?> encoder;
126
127 @SuppressWarnings( "unused" )
128 @Component( parameters = { "source=pagedSource", "elementName=prop:elementName", "value=inherit:value",
129 "volatile=true", "encoder=inherit:encoder", "index=index" } )
130 private Loop loop;
131
132 @Component( parameters = { "source=pagedSource", "rowsPerPage=rowsPerPage", "currentPage=currentPage" } )
133 private JSPager internalPager;
134
135 @Component( id = "CurrentPageHidden", parameters = { "value=currentPage", "translate=translate:integer" } )
136 private Hidden currentPageHidden;
137
138 @Component( id = "AddedRowsHidden", parameters = { "value=addedRowCount", "translate=translate:integer" } )
139 private Hidden addedRowHidden;
140
141 @SuppressWarnings( "unused" )
142 @Component( parameters = "to=pagerBottom" )
143 private Delegate pagerBottom;
144
145
146
147
148
149
150 @Parameter( value = "block:empty" )
151 private Block empty;
152
153 @Parameter( value = "block:bottomBlock" )
154 private Block bottomBlock;
155
156 @Parameter( value = "message:add.title.label", defaultPrefix = BindingConstants.LITERAL )
157 private String addRowLinkTitle;
158
159 private String assignedClientId;
160
161 private String addedRowCountHiddenName;
162
163 static class FormSubmitAction
164 implements ComponentAction<JSPagedLoop>
165 {
166
167 private static final long serialVersionUID = 456056528334001727L;
168
169 public void execute( JSPagedLoop component )
170 {
171 component.processFormAction();
172 }
173 }
174
175 static class SetupAction
176 implements ComponentAction<JSPagedLoop>
177 {
178
179 private static final long serialVersionUID = 6727709013577574475L;
180 private final String addedRowCountHiddenName;
181
182 public SetupAction( String controlName )
183 {
184 addedRowCountHiddenName = controlName;
185 }
186
187 public void execute( JSPagedLoop component )
188 {
189 component.setupAddedRowCountHiddenName( addedRowCountHiddenName );
190 }
191 }
192
193 private static final FormSubmitAction FORM_SUBMIT_ACTION = new FormSubmitAction();
194
195 private void setupAddedRowCountHiddenName( String name )
196 {
197 addedRowCountHiddenName = name;
198 }
199
200 Binding defaultSource()
201 {
202 return componentDefaultProvider.defaultBinding( "source", resources );
203 }
204
205 void setSource( Collection<Object> source )
206 {
207 this.source = source;
208 }
209
210 public String getAddRowLinkTitle()
211 {
212 return addRowLinkTitle;
213 }
214
215 public int getIndex()
216 {
217 return index;
218 }
219
220 public void setIndex( int index )
221 {
222 this.index = index;
223 }
224
225 public String getElementName()
226 {
227 return elementName;
228 }
229
230 public Block getBottomBlock()
231 {
232 return bottomBlock;
233 }
234
235 public Object getPagerBottom()
236 {
237 return internalPager;
238 }
239
240 public List<Object> getPagedSource()
241 {
242 return pagedSource;
243 }
244
245 public int getRowsPerPage()
246 {
247 return rowsPerPage;
248 }
249
250 public void setRowsPerPage( int rowsPerPage )
251 {
252 this.rowsPerPage = rowsPerPage;
253 }
254
255 public int getCurrentPage()
256 {
257 return currentPage;
258 }
259
260 public void setCurrentPage( int currentPage )
261 {
262 this.currentPage = currentPage;
263 }
264
265 public int getAddedRowCount()
266 {
267 return addedRowCount;
268 }
269
270 public void setAddedRowCount( int addedRowCount )
271 {
272 this.addedRowCount = addedRowCount;
273 }
274
275 public int getAdditionalRowCount()
276 {
277 return additionalRowCount;
278 }
279
280 public void setAdditionalRowCount( int additionalRowCount )
281 {
282 this.additionalRowCount = additionalRowCount;
283 }
284
285 public String getCurrentRowId()
286 {
287 String newId = renderSupport.allocateClientId( assignedClientId );
288 return String.format( "%s_row_%s", assignedClientId, newId.toLowerCase() );
289 }
290
291 public String getCurrentPageFieldName()
292 {
293 return currentPageHidden.getClientId();
294 }
295
296 public String getAddedRowFieldName()
297 {
298 return addedRowHidden.getClientId();
299 }
300
301 private PagerConfig config;
302
303 public PagerConfig getConfig()
304 {
305 return config;
306 }
307
308 public void setConfig( PagerConfig config )
309 {
310 this.config = config;
311 }
312
313 public String getDisplayStyle()
314 {
315 if ( getConfig() == null )
316 {
317 setConfig( internalPager.getConfig() );
318 }
319 PagerConfig config = getConfig();
320 int availableRows = config.getRowCount() - config.getAdditionalRowCount() + config.getAddedRowCount();
321
322 config.setMaxPages( ( ( availableRows - 1 ) / config.getRowsPerPage() ) + 1 );
323
324 if ( config.getMaxPages() > 0 && config.getCurrentPage() > config.getMaxPages() )
325 {
326 config.setCurrentPage( config.getMaxPages() );
327 }
328
329 int startIndex = config.getRowsPerPage() * ( config.getCurrentPage() - 1 );
330 int endIndex = startIndex + config.getRowsPerPage() - 1;
331
332 if ( index >= startIndex && index <= endIndex
333 && index < config.getRowCount() - config.getAdditionalRowCount() + config.getAddedRowCount() )
334 {
335 return "";
336 }
337 else
338 {
339 return "display:none;";
340 }
341 }
342
343 @SetupRender
344 Object setupRender()
345 {
346 currentPage = 1;
347 assignedClientId = renderSupport.allocateClientId( clientId );
348
349 if ( objectCreatorDelegate != null )
350 {
351 if ( null == addedRowsList ) addedRowsList = new ArrayList<Object>();
352 for ( int i = 0; i < additionalRowCount ; i++ )
353 {
354 Object object = objectCreatorDelegate.createObject();
355 addedRowsList.add( object );
356 }
357 }
358
359 pagedSource = new ArrayList<Object>();
360 if ( source != null ) pagedSource.addAll( source );
361 if ( null != addedRowsList ) pagedSource.addAll( addedRowsList );
362
363
364 if ( pagedSource.size() == 0 )
365 {
366 return empty;
367 }
368
369 return null;
370 }
371
372 Object beginRender()
373 {
374 environment.push( JSPagedLoop.class, this );
375
376
377
378 return pagedSource.size() != 0;
379
380 }
381
382 void afterRender()
383 {
384 formSupport.storeAndExecute( this, new SetupAction( addedRowHidden.getControlName() ) );
385 formSupport.store( this, FORM_SUBMIT_ACTION );
386 }
387
388 void cleanupRender()
389 {
390 environment.pop( JSPagedLoop.class );
391 }
392
393 void onActionFromAdd()
394 {
395
396 private void processFormAction()
397 {
398 int count = 0;
399 String sCount = null;
400 try
401 {
402 if ( addedRowCountHiddenName != null )
403 {
404 sCount = request.getParameter( addedRowCountHiddenName );
405 if ( sCount != null && sCount.trim().length() > 0 )
406 {
407 count = Integer.parseInt( sCount.trim() );
408 }
409 }
410 }
411 catch ( Exception e )
412 {
413 log.error( "Unable to parse AddedRowCount parameter: " + sCount );
414 }
415
416 if ( objectCreatorDelegate != null )
417 {
418 for ( int i = 0; i < count && i < addedRowsList.size() ; i++ )
419 {
420 objectCreatorDelegate.addNewObject( addedRowsList.get( i ) );
421 }
422 addedRowsList.clear();
423 }
424 addedRowCount = count;
425 }
426
427
428
429
430
431
432 public String getClientId()
433 {
434 return assignedClientId;
435 }
436
437 public String getFixedClientId()
438 {
439 return assignedClientId != null ? assignedClientId.toLowerCase() : "";
440 }
441 }