View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
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   * Scroller for UIData components eg. dataTable
58   *
59   * Must be nested inside footer facet of dataTable OR for
60   * attribute must be given so that corresponding uiData can be found.
61   *
62   * Unless otherwise specified, all attributes accept static values or EL expressions.
63   *
64   * A component which works together with a UIData component to allow a
65   * user to view a large list of data one "page" at a time, and navigate
66   * between pages.
67   *
68   * @since 1.1.7
69   * @author Thomas Spiegl (latest modification by $Author: hazems $)
70   * @version $Revision: 752423 $ $Date: 2009-03-11 06:10:49 -0500 (miƩ, 11 mar 2009) $
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     // TODO: JSF 2.1 put on Transient State
109     // just for caching the associated uidata
110     private transient UIData _UIData;
111 
112     // TODO: JSF 2.1 put on Transient State
113     //private transient Boolean _listLayout;
114 
115     // TODO: JSF 2.1 put on Transient State
116     //private transient Boolean _singleElementLayout;
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      *  The layout this scroller should render with. Default is 'table',
151      *  'list' is implemented as well. Additionally you can use
152      *  'singleList' - then the data-scroller will render a list, but
153      *  not the paginator - same with the value 'singleTable'.
154      *
155      */
156     @JSFProperty(
157        defaultValue = "table")
158     public abstract String getLayout();
159 
160     /**
161      * standard html colspan attribute for table cell
162      *
163      */
164     @JSFProperty(defaultValue = "Integer.MIN_VALUE")
165     public abstract int getColspan();
166 
167     /**
168      * HTML: Script to be invoked when the element is clicked.
169      *
170      */
171     @JSFProperty(clientEvent="click")
172     public abstract String getOnclick();
173 
174     /**
175      * HTML: Script to be invoked when the element is double-clicked.
176      *
177      */
178     @JSFProperty(clientEvent="dblclick")
179     public abstract String getOndblclick();
180 
181     public boolean isListLayout()
182     {
183         Boolean _listLayout;
184         //if(_listLayout == null)
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         //if(_singleElementLayout == null)
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      * Catch any attempts to queue events for this component, and ensure
220      * the event's phase is set appropriately. Events are expected to be
221      * queued by this component's renderer.
222      * <p>
223      * When this component is marked "immediate", any ActionEvent will
224      * be marked to fire in the "apply request values" phase. When this
225      * component is not immediate the event will fire during the
226      * "invoke application" phase instead.
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      * Invoke any action listeners attached to this class.
246      * <p>
247      * After listener invocation, the associated UIData's properties get
248      * updated:
249      * <ul>
250      * <li>if the user selected an absolute page# then setFirst is called with
251      * uiData.getRows() * pageNumber.
252      * <li>if the user selected the "first page" option then setFirst(0) is called.
253      * <li>if the user selected the "previous page" option then setFirst is decremented
254      * by uiData.getRows().
255      * <li>if the user selected the "fast rewind" option then setFirst is decremented
256      * by uiData.getRows() * fastStep.
257      * <li>next, fast-forward and last options have the obvious effect.
258      * </ul>
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             // huh? getUIData never returns null.
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         //there might be special cases where the first-property of the data-table
352         //is bound to a backing bean. If this happens, the user probably wants
353         //the data-scroller to update this backing-bean value - if not, you can always
354         //override this method in a subclass.
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      * @param event
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      * @return int
401      */
402     public UIData getUIData()
403     {
404         if (_UIData == null)
405         {
406             _UIData = findUIData();
407         }
408         return _UIData;
409     }
410 
411     /**
412      * @return the page index of the uidata
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      * @return the page count of the uidata
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      * @return int
467      */
468     public int getRowCount()
469     {
470         return getUIData().getRowCount();
471     }
472 
473     /**
474      * @return int
475      */
476     public int getRows()
477     {
478         return getUIData().getRows();
479     }
480 
481     /**
482      * @return int
483      */
484     public int getFirstRow()
485     {
486         return getUIData().getFirst();
487     }
488 
489     /**
490      * Find the UIData component associated with this scroller.
491      * <p>
492      * If the "for" attribute is not null then that value is used to find the
493      * specified component by id. Both "relative" and "absolute" ids are allowed;
494      * see method UIComponent.findComponent for details.
495      * <p>
496      * If the "for" attribute is not defined, then this component is expected to
497      * be a child of a UIData component.
498      *
499      * @throws IllegalArgumentException if an associated UIData component
500      * cannot be found.
501      */
502     protected UIData findUIData()
503     {
504         String forStr = getFor();
505         UIComponent forComp;
506         if (forStr == null)
507         {
508             // DataScroller may be a child of uiData
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      * @see javax.faces.component.ActionSource#getAction()
617      */
618     public MethodBinding getAction()
619     {
620         // not used
621         return null;
622     }
623 
624     /**
625      * @see javax.faces.component.ActionSource#setAction(javax.faces.el.MethodBinding)
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         // not used
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      * @see javax.faces.component.ActionSource#setActionListener(javax.faces.el.MethodBinding)
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      * MethodBinding pointing at method acception an ActionEvent with return type void.
667      *
668      * @see javax.faces.component.ActionSource#getActionListener()
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      * @see javax.faces.component.ActionSource#addActionListener(javax.faces.event.ActionListener)
690      */
691     public void addActionListener(ActionListener listener)
692     {
693         addFacesListener(listener);
694     }
695 
696     /**
697      * @see javax.faces.component.ActionSource#getActionListeners()
698      */
699     public ActionListener[] getActionListeners()
700     {
701         return (ActionListener[]) getFacesListeners(ActionListener.class);
702     }
703 
704     /**
705      * @see javax.faces.component.ActionSource#removeActionListener(javax.faces.event.ActionListener)
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                 //Delta
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                 //Full
738                 actionListenerSaved = saveAttachedState(facesContext,_actionListener);
739                 nullDelta = false;
740             }        
741             if (parentSaved == null && nullDelta)
742             {
743                 //No values
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             //Delta
773             ((StateHolder)_actionListener).restoreState(facesContext, ((AttachedDeltaWrapper) values[1]).getWrappedStateObject());
774         }
775         else
776         {
777             //Full
778             _actionListener = (javax.faces.el.MethodBinding) restoreAttachedState(facesContext,values[1]);
779         }         
780     }
781 
782     /**
783      * The JSF id of a UIData component that this scroller will affect.
784      *
785      * If this attribute is not present then the datascroller must be
786      * a child of a UIData component.
787      *
788      */
789     @JSFProperty
790     public abstract String getFor();
791 
792     /**
793      * step (pages) used for fastforward and fastrewind
794      *
795      */
796     @JSFProperty(defaultValue="Integer.MIN_VALUE")
797     public abstract int getFastStep();
798 
799     /**
800      * A parameter name, under which the actual page index is set
801      * in request scope similar to the var parameter.
802      *
803      */
804     @JSFProperty
805     public abstract String getPageIndexVar();
806 
807     /**
808      * A parameter name, under which the actual page count is set
809      * in request scope similar to the var parameter.
810      *
811      */
812     @JSFProperty
813     public abstract String getPageCountVar();
814 
815     /**
816      * A parameter name, under which the actual rows count is set
817      * in request scope similar to the var parameter.
818      *
819      * @JSFProperty
820      */
821     public abstract String getRowsCountVar();
822 
823     /**
824      * A parameter name, under which the actual displayed rows count
825      * is set in request scope similar to the var parameter.
826      *
827      */
828     @JSFProperty
829     public abstract String getDisplayedRowsCountVar();
830 
831     /**
832      * A parameter name, under which the actual first displayed row
833      * index is set in request scope similar to the var parameter.
834      *
835      */
836     @JSFProperty
837     public abstract String getFirstRowIndexVar();
838 
839     /**
840      * A parameter name, under which the actual last displayed row
841      * index is set in request scope similar to the var parameter.
842      *
843      */
844     @JSFProperty
845     public abstract String getLastRowIndexVar();
846 
847     /**
848      * If set true, then the paginator gets rendered
849      *
850      */
851     @JSFProperty(defaultValue = "false")
852     public abstract boolean isPaginator();
853 
854     /**
855      * The maximum amount of pages to be displayed in the paginator.
856      *
857      */
858     @JSFProperty(defaultValue="Integer.MIN_VALUE")
859     public abstract int getPaginatorMaxPages();
860 
861     /**
862      * styleclass for pagingator
863      *
864      */
865     @JSFProperty
866     public abstract String getPaginatorTableClass();
867 
868     /**
869      * style for pagingator
870      *
871      */
872     @JSFProperty
873     public abstract String getPaginatorTableStyle();
874 
875     /**
876      * styleClass for paginator's column
877      *
878      */
879     @JSFProperty
880     public abstract String getPaginatorColumnClass();
881 
882     /**
883      * style for paginator's column
884      *
885      */
886     @JSFProperty
887     public abstract String getPaginatorColumnStyle();
888 
889     /**
890      * styleClass for paginator's column with pageIndex = currentPageIndex
891      *
892      */
893     @JSFProperty
894     public abstract String getPaginatorActiveColumnClass();
895 
896     /**
897      * 'true' - render a link for the paginator's column with
898      * pageIndex = currentPageIndex. Default-value is 'true'.
899      *
900      */
901     @JSFProperty(defaultValue="true")
902     public abstract boolean isPaginatorRenderLinkForActive();
903 
904     /**
905      * style-class for data-scroller first-element
906      *
907      */
908     @JSFProperty
909     public abstract String getFirstStyleClass();
910 
911     /**
912      * style-class for data-scroller last-element
913      *
914      */
915     @JSFProperty
916     public abstract String getLastStyleClass();
917 
918     /**
919      * style-class for data-scroller previous-element
920      *
921      */
922     @JSFProperty
923     public abstract String getPreviousStyleClass();
924 
925     /**
926      * style-class for dataScroller next-element
927      *
928      */
929     @JSFProperty
930     public abstract String getNextStyleClass();
931 
932     /**
933      * style-class for data-scroller fast-forward-element
934      *
935      */
936     @JSFProperty
937     public abstract String getFastfStyleClass();
938 
939     /**
940      * style-class for data-scroller fast-rewind-element
941      *
942      */
943     @JSFProperty
944     public abstract String getFastrStyleClass();
945 
946     /**
947      * style for paginator's column with pageIndex = currentPageIndex
948      *
949      */
950     @JSFProperty
951     public abstract String getPaginatorActiveColumnStyle();
952 
953     /**
954      * If set to false, the facets aren't renderd if all the
955      * lines are contained on a single page. Default is true.
956      *
957      */
958     @JSFProperty(defaultValue="true")
959     public abstract boolean isRenderFacetsIfSinglePage();
960 
961     /**
962      * True means that the default ActionListener should be
963      * executed immediately (i.e. during Apply Request
964      * Values phase of the request processing lifecycle),
965      * rather than waiting until the Invoke Application phase.
966      *
967      */
968     @JSFProperty(defaultValue="false")
969     public abstract boolean isImmediate();
970 
971     /**
972      * If the dataScroller is on the first page (index is at 1), links for
973      * first, prev and fastprev are disabled. Default is false.
974      * 
975      */
976     @JSFProperty(defaultValue="false")
977     public abstract boolean isDisableFacetLinksIfFirstPage();
978 
979     /**
980      * If the dataScroller is on the last page (index is at pagecount), links for
981      * last, next and fastnext are disabled. Default is false.
982      * 
983      */
984     @JSFProperty(defaultValue="false")
985     public abstract boolean isDisableFacetLinksIfLastPage();
986 
987     /**
988      * If the dataScroller is on the first page (index is at 1), links for
989      * first, prev and fastprev are rendered. Default is true.
990      * 
991      */
992     @JSFProperty(defaultValue="true")
993     public abstract boolean isRenderFacetLinksIfFirstPage();
994 
995     /**
996      * If the dataScroller is on the last page (index is at pagecount), links for
997      * last, next and fastnext are rendered. Default is true.
998      * 
999      */
1000     @JSFProperty(defaultValue="true")
1001     public abstract boolean isRenderFacetLinksIfLastPage();
1002 
1003     enum PropertyKeys
1004     {
1005         actionListenerSet
1006     }
1007 }