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 event 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, null, 0, PropertyKey.Mutable.OFTEN);
78    static public final PropertyKey VALUE_KEY =
79      TYPE.registerKey("value", Object.class, null, 0, PropertyKey.Mutable.SOMETIMES);
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     try
146     {
147       HierarchyUtils.__setStartDepthPath(this, getStartLevel());
148       HierarchyUtils.__iterateOverTree(context,
149                                         phaseId,
150                                         this,
151                                         getDisclosedRowKeys(),
152                                         true);
153     }
154     finally
155     {
156       setRowKey(oldPath);
157     }
158   }
159 
160   @Override
161   protected boolean visitChildren(
162     VisitContext  visitContext,
163     VisitCallback callback)
164   {
165     if (ComponentUtils.isSkipIterationVisit(visitContext))
166     {
167       return visitChildrenWithoutIterating(visitContext, callback);
168     }
169     else
170     {
171       return visitData(visitContext, callback);
172     }
173   }
174 
175   @Override
176   protected boolean visitData(
177     VisitContext  visitContext,
178     VisitCallback callback)
179   {
180     Object oldRowKey = getRowKey();
181 
182     // if we are only visiting rendered stamps, then pass in the disclosed row keys, otherwise
183     // pass in null, indicating that all row keys should be visited
184     RowKeySet disclosedRowKeys = (visitContext.getHints().contains(VisitHint.SKIP_UNRENDERED))
185                                    ? getDisclosedRowKeys()
186                                    : null;
187 
188     boolean done;
189 
190     HierarchyUtils.__setStartDepthPath(this, getStartLevel());
191 
192     try
193     {
194       done = visitHierarchy(visitContext, callback, getStamps(), disclosedRowKeys);
195     }
196     finally
197     {
198       setRowKey(oldRowKey);
199     }
200 
201     return done;
202   }
203 
204   @Override
205   void __encodeBegin(FacesContext context) throws IOException
206   {
207     HierarchyUtils.__handleEncodeBegin(this, getDisclosedRowKeys());
208     super.__encodeBegin(context);
209   }
210 
211   @Override
212   void __init()
213   {
214     super.__init();
215     if (getDisclosedRowKeys() == null)
216       setDisclosedRowKeys(new RowKeySetTreeImpl());
217   }
218 
219   @Override
220   protected FacesBean createFacesBean(String rendererType)
221   {
222     return new RowKeyFacesBeanWrapper(super.createFacesBean(rendererType));
223   }
224 
225   private class RowKeyFacesBeanWrapper
226     extends FacesBeanWrapper
227   {
228     private boolean _retrievingDisclosedRows = false;
229 
230     RowKeyFacesBeanWrapper(FacesBean bean)
231     {
232       super(bean);
233     }
234 
235     @Override
236     public Object getProperty(PropertyKey key)
237     {
238       Object value = super.getProperty(key);
239 
240       if (key == DISCLOSED_ROW_KEYS_KEY && !_retrievingDisclosedRows && value instanceof RowKeySet)
241       {
242         // Ensure that when we are retrieving and setting the collection model, this property
243         // is not asked for which would create an infinite loop
244         _retrievingDisclosedRows = true;
245 
246         try
247         {
248           RowKeySet rowKeys = (RowKeySet) value;
249           // row key sets need the most recent collection model, but there is no one common entry
250           // point to set this on the set besides when code asks for the value from the bean
251           __flushCachedModel();  //insist that we populate with the very lastest instance of the collection model
252           rowKeys.setCollectionModel(getCollectionModel());
253         }
254         finally
255         {
256           _retrievingDisclosedRows = false;
257         }
258       }
259 
260       return value;
261     }
262 
263     @Override
264     public Object saveState(FacesContext context)
265     {
266       RowKeySet rowKeys = (RowKeySet)super.getProperty(DISCLOSED_ROW_KEYS_KEY);
267       if (rowKeys != null)
268       {
269         // make sure the set does not pin the model in memory
270         rowKeys.setCollectionModel(null);
271       }
272       return super.saveState(context);
273     }
274   }
275 
276   /**
277    * the component to use to stamp each element in the
278    *               tree. Only certain types of components are supported,
279    *               including all
280    *               components with no behavior and most components that implement the
281    *               EditableValueHolder or ActionSource interfaces.
282    */
283   final public UIComponent getNodeStamp()
284   {
285     return getFacet(NODE_STAMP_FACET);
286   }
287 
288   /**
289    * the component to use to stamp each element in the
290    *               tree. Only certain types of components are supported,
291    *               including all
292    *               components with no behavior and most components that implement the
293    *               EditableValueHolder or ActionSource interfaces.
294    */
295   @SuppressWarnings("unchecked")
296   final public void setNodeStamp(UIComponent nodeStampFacet)
297   {
298     getFacets().put(NODE_STAMP_FACET, nodeStampFacet);
299   }
300 
301   /**
302    * Gets a method reference to an ExpansionListener
303    *
304    * @return  the new rowDisclosureListener value
305    */
306   final public MethodExpression getRowDisclosureListener()
307   {
308     return (MethodExpression)getProperty(ROW_DISCLOSURE_LISTENER_KEY);
309   }
310 
311   /**
312    * Sets a method reference to an ExpansionListener
313    * 
314    * @param rowDisclosureListener  the new rowDisclosureListener value
315    */
316   final public void setRowDisclosureListener(MethodExpression rowDisclosureListener)
317   {
318     setProperty(ROW_DISCLOSURE_LISTENER_KEY, (rowDisclosureListener));
319   }
320 
321   /**
322    * Gets the set of disclosed rows for this component.
323    * Each entry in the set is a rowKey.
324    *
325    * @return  the new disclosedRowKeys value
326    */
327   final public RowKeySet getDisclosedRowKeys()
328   {
329     return (RowKeySet)getProperty(DISCLOSED_ROW_KEYS_KEY);
330   }
331 
332   /**
333    * Sets the set of disclosed rows for this component.
334    * Each entry in the set is a rowKey.
335    * 
336    * @param disclosedRowKeys  the new disclosedRowKeys value
337    */
338   final public void setDisclosedRowKeys(RowKeySet disclosedRowKeys)
339   {
340     setProperty(DISCLOSED_ROW_KEYS_KEY, (disclosedRowKeys));
341   }
342 
343   /**
344    * Gets the hierarchy of tree data - must be of type
345    *             org.apache.myfaces.trinidad.model.MenuModel
346    *
347    * @return  the new value value
348    */
349   final public Object getValue()
350   {
351     return getProperty(VALUE_KEY);
352   }
353 
354   /**
355    * Sets the hierarchy of tree data - must be of type
356    *             org.apache.myfaces.trinidad.model.MenuModel
357    * 
358    * @param value  the new value value
359    */
360   final public void setValue(Object value)
361   {
362     setProperty(VALUE_KEY, (value));
363   }
364 
365   /**
366    * Gets the starting level, based on a 0 based index, in the menuModel to render based on the focusPath of the menuModel.
367    *
368    * @return  the new startLevel value
369    */
370   final public int getStartLevel()
371   {
372     return ComponentUtils.resolveInteger(getProperty(START_LEVEL_KEY), 0);
373   }
374 
375   /**
376    * Sets the starting level, based on a 0 based index, in the menuModel to render based on the focusPath of the menuModel.
377    * 
378    * @param startLevel  the new startLevel value
379    */
380   final public void setStartLevel(int startLevel)
381   {
382     setProperty(START_LEVEL_KEY, Integer.valueOf(startLevel));
383   }
384 
385   /**
386    * Gets <html>
387    *  Name of the EL variable used to reference the varStatus information.
388    *           Once this component has completed rendering, this variable is
389    *           removed (or reverted back to its previous value).
390    *           The VarStatus provides contextual information about the state of the
391    *           component to EL expressions. For components that iterate, varStatus
392    *           also provides loop counter information.  Please see the this
393    *           component's documentation for the specific properties on the varStatus.
394    *           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>
395    *
396    * @return  the new varStatus value
397    */
398   final public String getVarStatus()
399   {
400     return ComponentUtils.resolveString(getProperty(VAR_STATUS_KEY));
401   }
402 
403   /**
404    * Sets <html>
405    *  Name of the EL variable used to reference the varStatus information.
406    *           Once this component has completed rendering, this variable is
407    *           removed (or reverted back to its previous value).
408    *           The VarStatus provides contextual information about the state of the
409    *           component to EL expressions. For components that iterate, varStatus
410    *           also provides loop counter information.  Please see the this
411    *           component's documentation for the specific properties on the varStatus.
412    *           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>
413    * 
414    * @param varStatus  the new varStatus value
415    */
416   final public void setVarStatus(String varStatus)
417   {
418     setProperty(VAR_STATUS_KEY, (varStatus));
419   }
420 
421   /**
422    * Gets whether data validation
423    *           should be skipped when row disclosure
424    *           events are generated by this component.
425    * 
426    *           When immediate is false (the default), events will
427    *           be delivered during the Invoke Application phase, which
428    *           will trigger validation.  When set to true,  events
429    *           will be executed during the Apply Request Values phase.
430    *
431    * @return  the new immediate value
432    */
433   final public boolean isImmediate()
434   {
435     return ComponentUtils.resolveBoolean(getProperty(IMMEDIATE_KEY), false);
436   }
437 
438   /**
439    * Sets whether data validation
440    *           should be skipped when row disclosure
441    *           events are generated by this component.
442    * 
443    *           When immediate is false (the default), events will
444    *           be delivered during the Invoke Application phase, which
445    *           will trigger validation.  When set to true,  events
446    *           will be executed during the Apply Request Values phase.
447    * 
448    * @param immediate  the new immediate value
449    */
450   final public void setImmediate(boolean immediate)
451   {
452     setProperty(IMMEDIATE_KEY, immediate ? Boolean.TRUE : Boolean.FALSE);
453   }
454 
455   /**
456    * Adds a rowDisclosure listener.
457    *
458    * @param listener  the rowDisclosure listener to add
459    */
460   final public void addRowDisclosureListener(
461     RowDisclosureListener listener)
462   {
463     addFacesListener(listener);
464   }
465 
466   /**
467    * Removes a rowDisclosure listener.
468    *
469    * @param listener  the rowDisclosure listener to remove
470    */
471   final public void removeRowDisclosureListener(
472     RowDisclosureListener listener)
473   {
474     removeFacesListener(listener);
475   }
476 
477   /**
478    * Returns an array of attached rowDisclosure listeners.
479    *
480    * @return  an array of attached rowDisclosure listeners.
481    */
482   final public RowDisclosureListener[] getRowDisclosureListeners()
483   {
484     return (RowDisclosureListener[])getFacesListeners(RowDisclosureListener.class);
485   }
486 
487   @Override
488   public String getFamily()
489   {
490     return COMPONENT_FAMILY;
491   }
492 
493   @Override
494   protected FacesBean.Type getBeanType()
495   {
496     return TYPE;
497   }
498 
499   /**
500    * Construct an instance of the UIXNavigationTree.
501    */
502   protected UIXNavigationTree(
503     String rendererType
504     )
505   {
506     super(rendererType);
507   }
508 
509   static
510   {
511     TYPE.lockAndRegister("org.apache.myfaces.trinidad.NavigationTree","org.apache.myfaces.trinidad.NavigationTree");
512   }
513 }