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 }