View Javadoc

1   // WARNING: This file was automatically generated. Do not edit it directly,
2   //          or you will lose your changes.
3   
4   /*
5    * Licensed to the Apache Software Foundation (ASF) under one
6    * or more contributor license agreements.  See the NOTICE file
7    * distributed with this work for additional information
8    * regarding copyright ownership.  The ASF licenses this file
9    * to you under the Apache License, Version 2.0 (the
10   * "License"); you may not use this file except in compliance
11   * with the License.  You may obtain a copy of the License at
12   *
13   *   http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing,
16   * software distributed under the License is distributed on an
17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   * KIND, either express or implied.  See the License for the
19   * specific language governing permissions and limitations
20   * under the License.
21  */
22  package org.apache.myfaces.trinidad.component;
23  
24  import java.io.IOException;
25  import javax.el.MethodExpression;
26  import javax.faces.component.UIComponent;
27  import javax.faces.component.visit.VisitCallback;
28  import javax.faces.component.visit.VisitContext;
29  import javax.faces.component.visit.VisitHint;
30  import javax.faces.context.FacesContext;
31  import javax.faces.event.AbortProcessingException;
32  import javax.faces.event.FacesEvent;
33  import javax.faces.event.PhaseId;
34  import org.apache.myfaces.trinidad.bean.FacesBean;
35  import org.apache.myfaces.trinidad.bean.PropertyKey;
36  import org.apache.myfaces.trinidad.event.RowDisclosureListener;
37  import org.apache.myfaces.trinidad.model.CollectionModel;
38  import org.apache.myfaces.trinidad.model.RowKeySet;
39  import org.apache.myfaces.trinidad.model.RowKeySetTreeImpl;
40  import org.apache.myfaces.trinidad.model.TreeModel;
41  import org.apache.myfaces.trinidad.util.ComponentUtils;
42  
43  /**
44   *
45   * <html:p>
46   * 
47   *             Apache Trinidad navigationTree components are used to display hierarchical navigation data.
48   *           </html:p>
49   *
50   * <h4>Events:</h4>
51   * <table border="1" width="100%" cellpadding="3" summary="">
52   * <tr bgcolor="#CCCCFF" class="TableHeadingColor">
53   * <th align="left">Type</th>
54   * <th align="left">Phases</th>
55   * <th align="left">Description</th>
56   * </tr>
57   * <tr class="TableRowColor">
58   * <td valign="top"><code>org.apache.myfaces.trinidad.event.RowDisclosureEvent</code></td>
59   * <td valign="top" nowrap>Apply<br>Request<br>Values<br>Invoke<br>Application</td>
60   * <td valign="top">The expansion event is generated for a table when the detail facet of a row is expanded or collapsed. For tree or a treeTable, the expansion
61                         event is generated when tree nodes are expanded or collapsed.</td>
62   * </tr>
63   * <tr class="TableRowColor">
64   * <td valign="top"><code>org.apache.myfaces.trinidad.event.AttributeChangeEvent</code></td>
65   * <td valign="top" nowrap>Invoke<br>Application<br>Apply<br>Request<br>Values</td>
66   * <td valign="top">Event delivered to describe an attribute change.  Attribute change events are not delivered for any programmatic change to a property.  They are only delivered when a renderer changes a property without the application's specific request.  An example of an attribute change events might include the width of a column that supported client-side resizing.</td>
67   * </tr>
68   * </table>
69   */
70  public class UIXNavigationTree extends UIXNavigationHierarchy
71  {
72    static public final FacesBean.Type TYPE = new FacesBean.Type(
73      UIXNavigationHierarchy.TYPE);
74    static public final PropertyKey ROW_DISCLOSURE_LISTENER_KEY =
75      TYPE.registerKey("rowDisclosureListener", MethodExpression.class);
76    static public final PropertyKey DISCLOSED_ROW_KEYS_KEY =
77      TYPE.registerKey("disclosedRowKeys", RowKeySet.class);
78    static public final PropertyKey VALUE_KEY =
79      TYPE.registerKey("value");
80    static public final PropertyKey START_LEVEL_KEY =
81      TYPE.registerKey("startLevel", Integer.class, Integer.valueOf(0));
82    static public final PropertyKey VAR_STATUS_KEY =
83      TYPE.registerKey("varStatus", String.class, PropertyKey.CAP_NOT_BOUND);
84    static public final PropertyKey IMMEDIATE_KEY =
85      TYPE.registerKey("immediate", Boolean.class, Boolean.FALSE);
86    static public final String NODE_STAMP_FACET = "nodeStamp";
87  
88    static public final String COMPONENT_FAMILY =
89      "org.apache.myfaces.trinidad.NavigationTree";
90    static public final String COMPONENT_TYPE =
91      "org.apache.myfaces.trinidad.NavigationTree";
92  
93    /**
94     * Construct an instance of the UIXNavigationTree.
95     */
96    public UIXNavigationTree()
97    {
98      super("org.apache.myfaces.trinidad.NavigationTree");
99    }
100   
101   /**
102    * Sets the phaseID of UI events depending on the "immediate" property.
103    */
104   @Override
105   public void queueEvent(FacesEvent event)
106   {
107     TableUtils.__handleQueueEvent(this, event);
108     super.queueEvent(event);
109   }
110 
111   /**
112    * Delivers an event.
113    * @param event
114    * @throws javax.faces.event.AbortProcessingException
115    */
116   @Override
117   public void broadcast(FacesEvent event) throws AbortProcessingException
118   {
119     HierarchyUtils.__handleBroadcast(this,
120                                       event,
121                                       getDisclosedRowKeys(),
122                                       getRowDisclosureListener());
123     super.broadcast(event);
124   }
125 
126   @Override
127   @SuppressWarnings("unchecked")
128   public CollectionModel createCollectionModel(CollectionModel current, Object value)
129   {
130     TreeModel model = (TreeModel)super.createCollectionModel(current, value);
131     RowKeySet treeState = getDisclosedRowKeys();
132     treeState.setCollectionModel(model);
133     return model;
134   }
135 
136   @Override
137   @SuppressWarnings("unchecked")
138   protected void processFacetsAndChildren(
139     FacesContext context,
140     PhaseId phaseId)
141   {
142     // this component has no facets that need to be processed once.
143     // instead process the "nodeStamp" facet as many times as necessary:
144     Object oldPath = getRowKey();
145     HierarchyUtils.__setStartDepthPath(this, getStartLevel());
146     HierarchyUtils.__iterateOverTree(context,
147                                       phaseId,
148                                       this,
149                                       getDisclosedRowKeys(),
150                                       true);
151     setRowKey(oldPath);
152   }
153 
154   @Override
155   protected boolean visitChildren(
156     VisitContext  visitContext,
157     VisitCallback callback)
158   {
159     return visitData(visitContext, callback);
160   }
161   
162   @Override
163   protected boolean visitData(
164     VisitContext  visitContext,
165     VisitCallback callback)
166   {
167     Object oldRowKey = getRowKey();
168 
169     // if we are only visiting rendered stamps, then pass in the disclosed row keys, otherwise
170     // pass in null, indicating that all row keys should be visited
171     RowKeySet disclosedRowKeys = (visitContext.getHints().contains(VisitHint.SKIP_UNRENDERED))
172                                    ? getDisclosedRowKeys()
173                                    : null;
174     
175     boolean done;
176 
177     HierarchyUtils.__setStartDepthPath(this, getStartLevel());
178 
179     try
180     {
181       done = visitHierarchy(visitContext, callback, getStamps(), disclosedRowKeys);
182     }
183     finally
184     {
185       setRowKey(oldRowKey);
186     }
187     
188     return done;
189   }
190   
191   @Override
192   void __encodeBegin(FacesContext context) throws IOException
193   {
194     HierarchyUtils.__handleEncodeBegin(this, getDisclosedRowKeys());
195     super.__encodeBegin(context);
196   }
197 
198   @Override
199   void __init()
200   {
201     super.__init();
202     if (getDisclosedRowKeys() == null)
203       setDisclosedRowKeys(new RowKeySetTreeImpl());
204   }
205 
206   @Override
207   protected FacesBean createFacesBean(String rendererType)
208   {
209     return new RowKeyFacesBeanWrapper(super.createFacesBean(rendererType));
210   }
211 
212   private class RowKeyFacesBeanWrapper
213     extends FacesBeanWrapper
214   {
215     private boolean _retrievingDisclosedRows = false;
216 
217     RowKeyFacesBeanWrapper(FacesBean bean)
218     {
219       super(bean);
220     }
221 
222     @Override
223     public Object getProperty(PropertyKey key)
224     {
225       Object value = super.getProperty(key);
226 
227       if (key == DISCLOSED_ROW_KEYS_KEY && !_retrievingDisclosedRows && value instanceof RowKeySet)
228       {
229         // Ensure that when we are retrieving and setting the collection model, this property
230         // is not asked for which would create an infinite loop
231         _retrievingDisclosedRows = true;
232 
233         try
234         {
235           RowKeySet rowKeys = (RowKeySet) value;
236           // row key sets need the most recent collection model, but there is no one common entry
237           // point to set this on the set besides when code asks for the value from the bean
238           rowKeys.setCollectionModel(getCollectionModel());
239         }
240         finally
241         {
242           _retrievingDisclosedRows = false;
243         }
244       }
245 
246       return value;
247     }
248 
249     @Override
250     public Object saveState(FacesContext context)
251     {
252       RowKeySet rowKeys = (RowKeySet)super.getProperty(DISCLOSED_ROW_KEYS_KEY);
253       if (rowKeys != null)
254       {
255         // make sure the set does not pin the model in memory
256         rowKeys.setCollectionModel(null);
257       }
258       return super.saveState(context);
259     }
260   }
261 
262   /**
263    * the component to use to stamp each element in the
264    *               tree. Only certain types of components are supported,
265    *               including all
266    *               components with no behavior and most components that implement the
267    *               EditableValueHolder or ActionSource interfaces.
268    */
269   final public UIComponent getNodeStamp()
270   {
271     return getFacet(NODE_STAMP_FACET);
272   }
273 
274   /**
275    * the component to use to stamp each element in the
276    *               tree. Only certain types of components are supported,
277    *               including all
278    *               components with no behavior and most components that implement the
279    *               EditableValueHolder or ActionSource interfaces.
280    */
281   @SuppressWarnings("unchecked")
282   final public void setNodeStamp(UIComponent nodeStampFacet)
283   {
284     getFacets().put(NODE_STAMP_FACET, nodeStampFacet);
285   }
286 
287   /**
288    * Gets a method reference to an ExpansionListener
289    *
290    * @return  the new rowDisclosureListener value
291    */
292   final public MethodExpression getRowDisclosureListener()
293   {
294     return (MethodExpression)getProperty(ROW_DISCLOSURE_LISTENER_KEY);
295   }
296 
297   /**
298    * Sets a method reference to an ExpansionListener
299    * 
300    * @param rowDisclosureListener  the new rowDisclosureListener value
301    */
302   final public void setRowDisclosureListener(MethodExpression rowDisclosureListener)
303   {
304     setProperty(ROW_DISCLOSURE_LISTENER_KEY, (rowDisclosureListener));
305   }
306 
307   /**
308    * Gets the set of disclosed rows for this component.
309    * Each entry in the set is a rowKey.
310    *
311    * @return  the new disclosedRowKeys value
312    */
313   final public RowKeySet getDisclosedRowKeys()
314   {
315     return (RowKeySet)getProperty(DISCLOSED_ROW_KEYS_KEY);
316   }
317 
318   /**
319    * Sets the set of disclosed rows for this component.
320    * Each entry in the set is a rowKey.
321    * 
322    * @param disclosedRowKeys  the new disclosedRowKeys value
323    */
324   final public void setDisclosedRowKeys(RowKeySet disclosedRowKeys)
325   {
326     setProperty(DISCLOSED_ROW_KEYS_KEY, (disclosedRowKeys));
327   }
328 
329   /**
330    * Gets the hierarchy of tree data - must be of type
331    *             org.apache.myfaces.trinidad.model.MenuModel
332    *
333    * @return  the new value value
334    */
335   final public Object getValue()
336   {
337     return getProperty(VALUE_KEY);
338   }
339 
340   /**
341    * Sets the hierarchy of tree data - must be of type
342    *             org.apache.myfaces.trinidad.model.MenuModel
343    * 
344    * @param value  the new value value
345    */
346   final public void setValue(Object value)
347   {
348     setProperty(VALUE_KEY, (value));
349   }
350 
351   /**
352    * Gets the starting level, based on a 0 based index, in the menuModel to render based on the focusPath of the menuModel.
353    *
354    * @return  the new startLevel value
355    */
356   final public int getStartLevel()
357   {
358     return ComponentUtils.resolveInteger(getProperty(START_LEVEL_KEY), 0);
359   }
360 
361   /**
362    * Sets the starting level, based on a 0 based index, in the menuModel to render based on the focusPath of the menuModel.
363    * 
364    * @param startLevel  the new startLevel value
365    */
366   final public void setStartLevel(int startLevel)
367   {
368     setProperty(START_LEVEL_KEY, Integer.valueOf(startLevel));
369   }
370 
371   /**
372    * Gets <html>
373    *  Name of the EL variable used to reference the varStatus information.
374    *           Once this component has completed rendering, this variable is
375    *           removed (or reverted back to its previous value).
376    *           The VarStatus provides contextual information about the state of the
377    *           component to EL expressions. For components that iterate, varStatus
378    *           also provides loop counter information.  Please see the this
379    *           component's documentation for the specific properties on the varStatus.
380    *           The common properties on varStatus include:<ul><li>"model" - returns the CollectionModel for this component</li><li>"index" - returns the zero based row index</li></ul></html>
381    *
382    * @return  the new varStatus value
383    */
384   final public String getVarStatus()
385   {
386     return ComponentUtils.resolveString(getProperty(VAR_STATUS_KEY));
387   }
388 
389   /**
390    * Sets <html>
391    *  Name of the EL variable used to reference the varStatus information.
392    *           Once this component has completed rendering, this variable is
393    *           removed (or reverted back to its previous value).
394    *           The VarStatus provides contextual information about the state of the
395    *           component to EL expressions. For components that iterate, varStatus
396    *           also provides loop counter information.  Please see the this
397    *           component's documentation for the specific properties on the varStatus.
398    *           The common properties on varStatus include:<ul><li>"model" - returns the CollectionModel for this component</li><li>"index" - returns the zero based row index</li></ul></html>
399    * 
400    * @param varStatus  the new varStatus value
401    */
402   final public void setVarStatus(String varStatus)
403   {
404     setProperty(VAR_STATUS_KEY, (varStatus));
405   }
406 
407   /**
408    * Gets whether data validation
409    *           should be skipped when row disclosure
410    *           events are generated by this component.
411    * 
412    *           When immediate is false (the default), events will
413    *           be delivered during the Invoke Application phase, which
414    *           will trigger validation.  When set to true,  events
415    *           will be executed during the Apply Request Values phase.
416    *
417    * @return  the new immediate value
418    */
419   final public boolean isImmediate()
420   {
421     return ComponentUtils.resolveBoolean(getProperty(IMMEDIATE_KEY), false);
422   }
423 
424   /**
425    * Sets whether data validation
426    *           should be skipped when row disclosure
427    *           events are generated by this component.
428    * 
429    *           When immediate is false (the default), events will
430    *           be delivered during the Invoke Application phase, which
431    *           will trigger validation.  When set to true,  events
432    *           will be executed during the Apply Request Values phase.
433    * 
434    * @param immediate  the new immediate value
435    */
436   final public void setImmediate(boolean immediate)
437   {
438     setProperty(IMMEDIATE_KEY, immediate ? Boolean.TRUE : Boolean.FALSE);
439   }
440 
441   /**
442    * Adds a rowDisclosure listener.
443    *
444    * @param listener  the rowDisclosure listener to add
445    */
446   final public void addRowDisclosureListener(
447     RowDisclosureListener listener)
448   {
449     addFacesListener(listener);
450   }
451 
452   /**
453    * Removes a rowDisclosure listener.
454    *
455    * @param listener  the rowDisclosure listener to remove
456    */
457   final public void removeRowDisclosureListener(
458     RowDisclosureListener listener)
459   {
460     removeFacesListener(listener);
461   }
462 
463   /**
464    * Returns an array of attached rowDisclosure listeners.
465    *
466    * @return  an array of attached rowDisclosure listeners.
467    */
468   final public RowDisclosureListener[] getRowDisclosureListeners()
469   {
470     return (RowDisclosureListener[])getFacesListeners(RowDisclosureListener.class);
471   }
472 
473   @Override
474   public String getFamily()
475   {
476     return COMPONENT_FAMILY;
477   }
478 
479   @Override
480   protected FacesBean.Type getBeanType()
481   {
482     return TYPE;
483   }
484 
485   /**
486    * Construct an instance of the UIXNavigationTree.
487    */
488   protected UIXNavigationTree(
489     String rendererType
490     )
491   {
492     super(rendererType);
493   }
494 
495   static
496   {
497     TYPE.lockAndRegister("org.apache.myfaces.trinidad.NavigationTree","org.apache.myfaces.trinidad.NavigationTree");
498   }
499 }