1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.custom.datascroller;
20
21 import javax.el.MethodExpression;
22 import javax.el.ValueExpression;
23 import javax.faces.FacesException;
24 import javax.faces.component.ActionSource2;
25 import javax.faces.component.PartialStateHolder;
26 import javax.faces.component.StateHolder;
27 import javax.faces.component.UIComponent;
28 import javax.faces.component.UIData;
29 import javax.faces.component.UIPanel;
30 import javax.faces.component.behavior.ClientBehaviorHolder;
31 import javax.faces.context.FacesContext;
32 import javax.faces.el.EvaluationException;
33 import javax.faces.el.MethodBinding;
34 import javax.faces.el.ValueBinding;
35 import javax.faces.event.AbortProcessingException;
36 import javax.faces.event.ActionEvent;
37 import javax.faces.event.ActionListener;
38 import javax.faces.event.FacesEvent;
39 import javax.faces.event.PhaseId;
40
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
44 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFacet;
45 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
46 import org.apache.myfaces.component.AttachedDeltaWrapper;
47 import org.apache.myfaces.component.DisplayValueOnlyAware;
48 import org.apache.myfaces.component.ForceIdAware;
49 import org.apache.myfaces.component.StyleAware;
50 import org.apache.myfaces.component.UniversalProperties;
51 import org.apache.myfaces.component.UserRoleAware;
52 import org.apache.myfaces.component.UserRoleUtils;
53 import org.apache.myfaces.component.html.util.HtmlComponentUtils;
54 import org.apache.myfaces.shared_tomahawk.component.DisplayValueOnlyCapable;
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 @JSFComponent(
73 name = "t:dataScroller",
74 clazz = "org.apache.myfaces.custom.datascroller.HtmlDataScroller",
75 tagClass = "org.apache.myfaces.custom.datascroller.HtmlDataScrollerTag",
76 defaultEventName = "action")
77 public abstract class AbstractHtmlDataScroller extends UIPanel
78 implements ActionSource2, ClientBehaviorHolder, UserRoleAware, DisplayValueOnlyCapable,
79 DisplayValueOnlyAware, ForceIdAware, UniversalProperties, StyleAware
80 {
81
82 public static final String COMPONENT_TYPE = "org.apache.myfaces.HtmlDataScroller";
83 public static final String COMPONENT_FAMILY = "javax.faces.Panel";
84 private static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.DataScroller";
85 private static final boolean DEFAULT_IMMEDIATE = false;
86
87 private static final Log log = LogFactory.getLog(AbstractHtmlDataScroller.class);
88
89 private static final String FIRST_FACET_NAME = "first";
90 private static final String LAST_FACET_NAME = "last";
91 private static final String NEXT_FACET_NAME = "next";
92 private static final String PREVIOUS_FACET_NAME = "previous";
93 private static final String FAST_FORWARD_FACET_NAME = "fastforward";
94 private static final String FAST_REWIND_FACET_NAME = "fastrewind";
95
96 public static final String FACET_FIRST = "first".intern();
97 public static final String FACET_PREVIOUS = "previous".intern();
98 public static final String FACET_NEXT = "next".intern();
99 public static final String FACET_LAST = "last".intern();
100 public static final String FACET_FAST_FORWARD = "fastf".intern();
101 public static final String FACET_FAST_REWIND = "fastr".intern();
102
103 private static final String TABLE_LAYOUT = "table";
104 private static final String LIST_LAYOUT = "list";
105 private static final String SINGLE_LIST_LAYOUT = "singleList";
106 private static final String SINGLE_TABLE_LAYOUT = "singleTable";
107
108
109
110 private transient UIData _UIData;
111
112
113
114
115
116
117
118 private MethodBinding _actionListener;
119
120 public String getClientId(FacesContext context)
121 {
122 String clientId = HtmlComponentUtils.getClientId(this, getRenderer(context), context);
123 if (clientId == null)
124 {
125 clientId = super.getClientId(context);
126 }
127
128 return clientId;
129 }
130
131 public boolean isRendered()
132 {
133 if (!UserRoleUtils.isVisibleOnUserRole(this)) return false;
134 return super.isRendered();
135 }
136
137 public boolean isSetDisplayValueOnly(){
138 return getDisplayValueOnly() != null ? true : false;
139 }
140
141 public boolean isDisplayValueOnly(){
142 return getDisplayValueOnly() != null ? getDisplayValueOnly().booleanValue() : false;
143 }
144
145 public void setDisplayValueOnly(boolean displayValueOnly){
146 this.setDisplayValueOnly((Boolean) Boolean.valueOf(displayValueOnly));
147 }
148
149
150
151
152
153
154
155
156 @JSFProperty(
157 defaultValue = "table")
158 public abstract String getLayout();
159
160
161
162
163
164 @JSFProperty(defaultValue = "Integer.MIN_VALUE")
165 public abstract int getColspan();
166
167
168
169
170
171 @JSFProperty(clientEvent="click")
172 public abstract String getOnclick();
173
174
175
176
177
178 @JSFProperty(clientEvent="dblclick")
179 public abstract String getOndblclick();
180
181 public boolean isListLayout()
182 {
183 Boolean _listLayout;
184
185
186 String layout=getLayout();
187 if(layout == null || layout.equals(TABLE_LAYOUT) || layout.equals(SINGLE_TABLE_LAYOUT))
188 _listLayout = Boolean.FALSE;
189 else if(layout.equals(LIST_LAYOUT) || layout.equals(SINGLE_LIST_LAYOUT))
190 {
191 _listLayout = Boolean.TRUE;
192 }
193 else
194 {
195 log.error("Invalid layout-parameter : "+layout +" provided. Defaulting to table-layout.");
196 _listLayout = Boolean.FALSE;
197 }
198
199
200 return _listLayout.booleanValue();
201 }
202
203 public boolean isSingleElementLayout()
204 {
205 Boolean _singleElementLayout;
206
207
208 String layout=getLayout();
209 if(layout == null || layout.equals(SINGLE_LIST_LAYOUT) || layout.equals(SINGLE_TABLE_LAYOUT))
210 _singleElementLayout = Boolean.TRUE;
211 else
212 _singleElementLayout = Boolean.FALSE;
213
214
215 return _singleElementLayout.booleanValue();
216 }
217
218
219
220
221
222
223
224
225
226
227
228 public void queueEvent(FacesEvent event)
229 {
230 if (event != null && event instanceof ActionEvent)
231 {
232 if (isImmediate())
233 {
234 event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
235 }
236 else
237 {
238 event.setPhaseId(PhaseId.INVOKE_APPLICATION);
239 }
240 }
241 super.queueEvent(event);
242 }
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 public void broadcast(FacesEvent event) throws AbortProcessingException
261 {
262 super.broadcast(event);
263
264 if (event instanceof ScrollerActionEvent)
265 {
266 ScrollerActionEvent scrollerEvent = (ScrollerActionEvent) event;
267
268 broadcastToActionListener(scrollerEvent);
269
270
271 UIData uiData = getUIData();
272 if (uiData == null)
273 {
274 return;
275 }
276
277 int pageindex = scrollerEvent.getPageIndex();
278 if (pageindex == -1)
279 {
280 String facet = scrollerEvent.getScrollerfacet();
281 if (FACET_FIRST.equals(facet))
282 {
283 setFirst(uiData, 0);
284 }
285 else if (FACET_PREVIOUS.equals(facet))
286 {
287 int previous = uiData.getFirst() - uiData.getRows();
288 if (previous >= 0)
289 setFirst(uiData, previous);
290 }
291 else if (FACET_NEXT.equals(facet))
292 {
293 int next = uiData.getFirst() + uiData.getRows();
294 if (next < uiData.getRowCount())
295 setFirst(uiData, next);
296 }
297 else if (FACET_FAST_FORWARD.equals(facet))
298 {
299 int fastStep = getFastStep();
300 if (fastStep <= 0)
301 fastStep = 1;
302 int next = uiData.getFirst() + uiData.getRows() * fastStep;
303 int rowcount = uiData.getRowCount();
304 if (next >= rowcount)
305 next = (rowcount - 1) - ((rowcount - 1) % uiData.getRows());
306 setFirst(uiData, next);
307 }
308 else if (FACET_FAST_REWIND.equals(facet))
309 {
310 int fastStep = getFastStep();
311 if (fastStep <= 0)
312 fastStep = 1;
313 int previous = uiData.getFirst() - uiData.getRows() * fastStep;
314 if (previous < 0)
315 previous = 0;
316 setFirst(uiData, previous);
317 }
318 else if (FACET_LAST.equals(facet))
319 {
320 int rowcount = uiData.getRowCount();
321 int rows = uiData.getRows();
322 int delta = (rows != 0) ? (rowcount % rows) : 0;
323 int first = delta > 0 && delta < rows ? rowcount - delta : rowcount - rows;
324 if (first >= 0)
325 {
326 setFirst(uiData, first);
327 }
328 else
329 {
330 setFirst(uiData, 0);
331 }
332 }
333 }
334 else
335 {
336 int pageCount = getPageCount();
337 if (pageindex > pageCount)
338 {
339 pageindex = pageCount;
340 }
341 if (pageindex <= 0)
342 {
343 pageindex = 1;
344 }
345 setFirst(uiData, uiData.getRows() * (pageindex - 1));
346 }
347 }
348 }
349
350 protected void setFirst(UIData uiData, int value) {
351
352
353
354
355 if(uiData.getValueBinding("first")!=null)
356 {
357 ValueBinding vb = uiData.getValueBinding("first");
358 vb.setValue(getFacesContext(),new Integer(value));
359 }
360 else
361 {
362 uiData.setFirst(value);
363 }
364 }
365
366
367
368
369 protected void broadcastToActionListener(ScrollerActionEvent event)
370 {
371 FacesContext context = getFacesContext();
372
373 MethodBinding actionListenerBinding = getActionListener();
374 if (actionListenerBinding != null)
375 {
376 try
377 {
378 actionListenerBinding.invoke(context, new Object[] {event});
379 }
380 catch (EvaluationException e)
381 {
382 Throwable cause = e.getCause();
383 if (cause != null && cause instanceof AbortProcessingException)
384 {
385 throw (AbortProcessingException)cause;
386 }
387 throw e;
388 }
389 }
390
391 ActionListener defaultActionListener
392 = context.getApplication().getActionListener();
393 if (defaultActionListener != null)
394 {
395 defaultActionListener.processAction((ActionEvent)event);
396 }
397 }
398
399
400
401
402 public UIData getUIData()
403 {
404 if (_UIData == null)
405 {
406 _UIData = findUIData();
407 }
408 return _UIData;
409 }
410
411
412
413
414 public int getPageIndex()
415 {
416 UIData uiData = getUIData();
417 int rows = uiData.getRows();
418 if (0 == rows)
419 {
420 throw new FacesException("You need to set a value to the 'rows' attribute of component '" + uiData.getClientId(getFacesContext()) + "'" );
421 }
422
423 int pageIndex;
424 if (rows > 0)
425 {
426 pageIndex = uiData.getFirst() / rows + 1;
427 }
428 else
429 {
430 log.warn("DataTable " + uiData.getClientId(FacesContext.getCurrentInstance())
431 + " has invalid rows attribute.");
432 pageIndex = 0;
433 }
434 if (uiData.getFirst() % rows > 0)
435 {
436 pageIndex++;
437 }
438 return pageIndex;
439 }
440
441
442
443
444 public int getPageCount()
445 {
446 UIData uiData = getUIData();
447 int rows = uiData.getRows();
448 int pageCount;
449 if (rows > 0)
450 {
451 pageCount = rows <= 0 ? 1 : uiData.getRowCount() / rows;
452 if (uiData.getRowCount() % rows > 0)
453 {
454 pageCount++;
455 }
456 }
457 else
458 {
459 rows = 1;
460 pageCount = 1;
461 }
462 return pageCount;
463 }
464
465
466
467
468 public int getRowCount()
469 {
470 return getUIData().getRowCount();
471 }
472
473
474
475
476 public int getRows()
477 {
478 return getUIData().getRows();
479 }
480
481
482
483
484 public int getFirstRow()
485 {
486 return getUIData().getFirst();
487 }
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502 protected UIData findUIData()
503 {
504 String forStr = getFor();
505 UIComponent forComp;
506 if (forStr == null)
507 {
508
509 forComp = getParent();
510 }
511 else
512 {
513 forComp = findComponent(forStr);
514 }
515 if (forComp == null)
516 {
517 throw new IllegalArgumentException(
518 "could not find UIData referenced by attribute dataScroller@for = '"
519 + forStr + "'");
520 }
521 else if (!(forComp instanceof UIData))
522 {
523 throw new IllegalArgumentException(
524 "uiComponent referenced by attribute dataScroller@for = '"
525 + forStr + "' must be of type " + UIData.class.getName()
526 + ", not type " + forComp.getClass().getName());
527 }
528 return (UIData) forComp;
529 }
530
531 public void setFirst(UIComponent first)
532 {
533 getFacets().put(FIRST_FACET_NAME, first);
534 }
535
536
537
538 @JSFFacet
539 public UIComponent getFirst()
540 {
541 return (UIComponent) getFacets().get(FIRST_FACET_NAME);
542 }
543
544 public void setLast(UIComponent last)
545 {
546 getFacets().put(LAST_FACET_NAME, last);
547 }
548
549
550
551 @JSFFacet
552 public UIComponent getLast()
553 {
554 return (UIComponent) getFacets().get(LAST_FACET_NAME);
555 }
556
557 public void setNext(UIComponent next)
558 {
559 getFacets().put(NEXT_FACET_NAME, next);
560 }
561
562
563
564 @JSFFacet
565 public UIComponent getNext()
566 {
567 return (UIComponent) getFacets().get(NEXT_FACET_NAME);
568 }
569
570 public void setFastForward(UIComponent previous)
571 {
572 getFacets().put(FAST_FORWARD_FACET_NAME, previous);
573 }
574
575
576
577 @JSFFacet
578 public UIComponent getFastForward()
579 {
580 return (UIComponent) getFacets().get(FAST_FORWARD_FACET_NAME);
581 }
582
583 public void setFastRewind(UIComponent previous)
584 {
585 getFacets().put(FAST_REWIND_FACET_NAME, previous);
586 }
587
588
589
590 @JSFFacet
591 public UIComponent getFastRewind()
592 {
593 return (UIComponent) getFacets().get(FAST_REWIND_FACET_NAME);
594 }
595
596 public void setPrevious(UIComponent previous)
597 {
598 getFacets().put(PREVIOUS_FACET_NAME, previous);
599 }
600
601
602
603
604 @JSFFacet
605 public UIComponent getPrevious()
606 {
607 return (UIComponent) getFacets().get(PREVIOUS_FACET_NAME);
608 }
609
610 public boolean getRendersChildren()
611 {
612 return true;
613 }
614
615
616
617
618 public MethodBinding getAction()
619 {
620
621 return null;
622 }
623
624
625
626
627 public void setAction(MethodBinding action)
628 {
629 throw new UnsupportedOperationException(
630 "defining an action is not supported. use an actionlistener");
631 }
632
633 @JSFProperty(stateHolder=true, returnSignature = "java.lang.Object", jspName = "action", clientEvent="action")
634 public MethodExpression getActionExpression()
635 {
636
637 return null;
638 }
639
640 public void setActionExpression(MethodExpression action)
641 {
642 throw new UnsupportedOperationException(
643 "defining an action is not supported. use an actionlistener");
644 }
645
646
647
648
649
650 public void setActionListener(MethodBinding actionListener)
651 {
652 _actionListener = actionListener;
653 if (initialStateMarked())
654 {
655 getStateHelper().put(PropertyKeys.actionListenerSet,Boolean.TRUE);
656 }
657 }
658
659 private boolean _isSetActionListener()
660 {
661 Boolean value = (Boolean) getStateHelper().get(PropertyKeys.actionListenerSet);
662 return value == null ? false : value;
663 }
664
665
666
667
668
669
670 @JSFProperty(
671 returnSignature="void",
672 methodSignature="javax.faces.event.ActionEvent")
673 public MethodBinding getActionListener()
674 {
675 if (_actionListener != null)
676 {
677 return _actionListener;
678 }
679 ValueExpression expression = getValueExpression("actionListener");
680 if (expression != null)
681 {
682 return (MethodBinding) expression.getValue(getFacesContext()
683 .getELContext());
684 }
685 return null;
686 }
687
688
689
690
691 public void addActionListener(ActionListener listener)
692 {
693 addFacesListener(listener);
694 }
695
696
697
698
699 public ActionListener[] getActionListeners()
700 {
701 return (ActionListener[]) getFacesListeners(ActionListener.class);
702 }
703
704
705
706
707 public void removeActionListener(ActionListener listener)
708 {
709 removeFacesListener(listener);
710 }
711
712 public Object saveState(FacesContext facesContext)
713 {
714 if (initialStateMarked())
715 {
716 boolean nullDelta = true;
717 Object parentSaved = super.saveState(facesContext);
718 Object actionListenerSaved = null;
719 if (!_isSetActionListener() &&
720 _actionListener != null && _actionListener instanceof PartialStateHolder)
721 {
722
723 StateHolder holder = (StateHolder) _actionListener;
724 if (!holder.isTransient())
725 {
726 Object attachedState = holder.saveState(facesContext);
727 if (attachedState != null)
728 {
729 nullDelta = false;
730 }
731 actionListenerSaved = new AttachedDeltaWrapper(_actionListener.getClass(),
732 attachedState);
733 }
734 }
735 else if (_isSetActionListener() || _actionListener != null)
736 {
737
738 actionListenerSaved = saveAttachedState(facesContext,_actionListener);
739 nullDelta = false;
740 }
741 if (parentSaved == null && nullDelta)
742 {
743
744 return null;
745 }
746
747 Object[] values = new Object[2];
748 values[0] = parentSaved;
749 values[1] = actionListenerSaved;
750 return values;
751 }
752 else
753 {
754 Object[] values = new Object[2];
755 values[0] = super.saveState(facesContext);
756 values[1] = saveAttachedState(facesContext,_actionListener);
757 return values;
758 }
759 }
760
761 public void restoreState(FacesContext facesContext, Object state)
762 {
763 if (state == null)
764 {
765 return;
766 }
767
768 Object[] values = (Object[])state;
769 super.restoreState(facesContext,values[0]);
770 if (values[1] instanceof AttachedDeltaWrapper)
771 {
772
773 ((StateHolder)_actionListener).restoreState(facesContext, ((AttachedDeltaWrapper) values[1]).getWrappedStateObject());
774 }
775 else
776 {
777
778 _actionListener = (javax.faces.el.MethodBinding) restoreAttachedState(facesContext,values[1]);
779 }
780 }
781
782
783
784
785
786
787
788
789 @JSFProperty
790 public abstract String getFor();
791
792
793
794
795
796 @JSFProperty(defaultValue="Integer.MIN_VALUE")
797 public abstract int getFastStep();
798
799
800
801
802
803
804 @JSFProperty
805 public abstract String getPageIndexVar();
806
807
808
809
810
811
812 @JSFProperty
813 public abstract String getPageCountVar();
814
815
816
817
818
819
820
821 public abstract String getRowsCountVar();
822
823
824
825
826
827
828 @JSFProperty
829 public abstract String getDisplayedRowsCountVar();
830
831
832
833
834
835
836 @JSFProperty
837 public abstract String getFirstRowIndexVar();
838
839
840
841
842
843
844 @JSFProperty
845 public abstract String getLastRowIndexVar();
846
847
848
849
850
851 @JSFProperty(defaultValue = "false")
852 public abstract boolean isPaginator();
853
854
855
856
857
858 @JSFProperty(defaultValue="Integer.MIN_VALUE")
859 public abstract int getPaginatorMaxPages();
860
861
862
863
864
865 @JSFProperty
866 public abstract String getPaginatorTableClass();
867
868
869
870
871
872 @JSFProperty
873 public abstract String getPaginatorTableStyle();
874
875
876
877
878
879 @JSFProperty
880 public abstract String getPaginatorColumnClass();
881
882
883
884
885
886 @JSFProperty
887 public abstract String getPaginatorColumnStyle();
888
889
890
891
892
893 @JSFProperty
894 public abstract String getPaginatorActiveColumnClass();
895
896
897
898
899
900
901 @JSFProperty(defaultValue="true")
902 public abstract boolean isPaginatorRenderLinkForActive();
903
904
905
906
907
908 @JSFProperty
909 public abstract String getFirstStyleClass();
910
911
912
913
914
915 @JSFProperty
916 public abstract String getLastStyleClass();
917
918
919
920
921
922 @JSFProperty
923 public abstract String getPreviousStyleClass();
924
925
926
927
928
929 @JSFProperty
930 public abstract String getNextStyleClass();
931
932
933
934
935
936 @JSFProperty
937 public abstract String getFastfStyleClass();
938
939
940
941
942
943 @JSFProperty
944 public abstract String getFastrStyleClass();
945
946
947
948
949
950 @JSFProperty
951 public abstract String getPaginatorActiveColumnStyle();
952
953
954
955
956
957
958 @JSFProperty(defaultValue="true")
959 public abstract boolean isRenderFacetsIfSinglePage();
960
961
962
963
964
965
966
967
968 @JSFProperty(defaultValue="false")
969 public abstract boolean isImmediate();
970
971
972
973
974
975
976 @JSFProperty(defaultValue="false")
977 public abstract boolean isDisableFacetLinksIfFirstPage();
978
979
980
981
982
983
984 @JSFProperty(defaultValue="false")
985 public abstract boolean isDisableFacetLinksIfLastPage();
986
987
988
989
990
991
992 @JSFProperty(defaultValue="true")
993 public abstract boolean isRenderFacetLinksIfFirstPage();
994
995
996
997
998
999
1000 @JSFProperty(defaultValue="true")
1001 public abstract boolean isRenderFacetLinksIfLastPage();
1002
1003 enum PropertyKeys
1004 {
1005 actionListenerSet
1006 }
1007 }