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.navmenu.htmlnavmenu;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.List;
25  import java.util.Map;
26  
27  import javax.faces.component.UIComponent;
28  import javax.faces.component.UIGraphic;
29  import javax.faces.component.UIOutput;
30  import javax.faces.component.UISelectItems;
31  import javax.faces.component.UIViewRoot;
32  import javax.faces.component.behavior.ClientBehavior;
33  import javax.faces.component.behavior.ClientBehaviorHolder;
34  import javax.faces.context.FacesContext;
35  import javax.faces.context.ResponseWriter;
36  import javax.faces.el.ValueBinding;
37  import javax.faces.event.ActionListener;
38  import javax.faces.event.ComponentSystemEvent;
39  import javax.faces.event.ComponentSystemEventListener;
40  import javax.faces.event.ListenerFor;
41  
42  import org.apache.commons.logging.Log;
43  import org.apache.commons.logging.LogFactory;
44  import org.apache.myfaces.custom.navmenu.NavigationMenuItem;
45  import org.apache.myfaces.custom.navmenu.NavigationMenuUtils;
46  import org.apache.myfaces.custom.navmenu.UINavigationMenuItem;
47  import org.apache.myfaces.renderkit.html.ext.HtmlLinkRenderer;
48  import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
49  import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
50  import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
51  import org.apache.myfaces.shared_tomahawk.renderkit.html.util.ResourceUtils;
52  import org.apache.myfaces.tomahawk.application.PreRenderViewAddResourceEvent;
53  import org.apache.myfaces.tomahawk.util.TomahawkResourceUtils;
54  
55  /**
56   * Many thanks to the guys from Swiss Federal Institute of Intellectual Property & Marc Bouquet
57   * for helping to develop this component.
58   *
59   * @JSFRenderer
60   *   renderKitId = "HTML_BASIC" 
61   *   family = "javax.faces.Panel"
62   *   type = "org.apache.myfaces.NavigationMenu"
63   *   
64   * @JSFRenderer
65   *   renderKitId = "HTML_BASIC" 
66   *   family = "javax.faces.Command"
67   *   type = "org.apache.myfaces.NavigationMenu"
68   *
69   * @author Thomas Spiegl
70   * @author Manfred Geiler
71   */
72  @ListenerFor(systemEventClass=PreRenderViewAddResourceEvent.class)
73  public class HtmlNavigationMenuRenderer extends HtmlLinkRenderer
74      implements ComponentSystemEventListener
75  {
76      private static final Log log = LogFactory.getLog(HtmlNavigationMenuRenderer.class);
77  
78      public static final String RENDERER_TYPE = "org.apache.myfaces.NavigationMenu";
79  
80      private static final Integer ZERO_INTEGER = new Integer(0);
81  
82      private static final String HORIZ_MENU_SCRIPT = "HMenuIEHover.js";
83  
84      public void processEvent(ComponentSystemEvent event)
85      {
86          if (event.getComponent() instanceof HtmlPanelNavigationMenu)
87          {
88              HtmlPanelNavigationMenu panelNav = (HtmlPanelNavigationMenu) event.getComponent();
89              if (HtmlNavigationMenuRendererUtils.isListLayout(panelNav))
90              {
91                  if (panelNav.isRenderAll())
92                  {
93                      addResourcesToHeader(FacesContext.getCurrentInstance());
94                  }
95              }
96          }
97      }
98  
99      public boolean getRendersChildren() {
100         return true;
101     }
102 
103     public void decode(FacesContext facesContext, UIComponent component) {
104         if (component instanceof HtmlCommandNavigationItem) {
105             //HtmlCommandNavigation
106             super.decode(facesContext, component);
107         }
108         else
109         {
110             HtmlRendererUtils.decodeClientBehaviors(facesContext, component);
111         }
112     }
113 
114     public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
115         if (component instanceof HtmlCommandNavigationItem) {
116             //HtmlCommandNavigationItem
117             super.encodeBegin(facesContext, component);
118         }
119     }
120 
121     public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException {
122         if (component instanceof HtmlCommandNavigationItem) {
123             //HtmlCommandNavigationItem
124             super.encodeChildren(facesContext, component);
125         }
126     }
127 
128     public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
129         if (component instanceof HtmlCommandNavigationItem) {
130             //HtmlCommandNavigationItem
131             super.encodeEnd(facesContext, component);
132             return;
133         }
134         else
135         {
136             Map<String, List<ClientBehavior>> behaviors = null;
137             if (component instanceof ClientBehaviorHolder)
138             {
139                 behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
140                 if (!behaviors.isEmpty())
141                 {
142                     ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, facesContext.getResponseWriter());
143                 }
144             }
145         }
146         RendererUtils.checkParamValidity(facesContext, component, HtmlPanelNavigationMenu.class);
147         HtmlPanelNavigationMenu panelNav = (HtmlPanelNavigationMenu) component;
148 
149         if (HtmlNavigationMenuRendererUtils.isListLayout(panelNav)) {
150             boolean preprocess = true;
151             boolean clientStateSaving = facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext);
152             if (clientStateSaving) {
153                 // client statesaving
154                 HtmlPanelNavigationMenu panelNavPrev = findPreviousPanelNav(facesContext, panelNav);
155                 if (panelNavPrev != null) {
156                     preprocess = false;
157                     if (!panelNavPrev.equals(panelNav)) {
158                         // substitute panelnav
159                         UIComponent parent = panelNav.getParent();
160                         int insertPos = parent.getChildren().indexOf(panelNav);
161                         parent.getChildren().set(insertPos, panelNavPrev);
162                         panelNavPrev.setParent(parent);
163                         panelNav.setParent(null);
164                         panelNav = panelNavPrev;
165                     }
166                 }
167             }
168             else {
169                 // server statesaving
170                 if (panelNav.getPreprocessed() != null && panelNav.getPreprocessed().booleanValue())
171                     preprocess = false;
172             }
173             if (preprocess) {
174                 panelNav.setPreprocessed(Boolean.TRUE);
175                 preprocessNavigationItems(facesContext, panelNav, panelNav.getChildren(), new UniqueId());
176                 if (!clientStateSaving) {
177                     HtmlPanelNavigationMenu panelNavPrev = findPreviousPanelNav(facesContext, panelNav);
178                     if (panelNavPrev != null) {
179                         restoreOpenActiveStates(facesContext, panelNav, panelNavPrev.getChildren());
180                     }
181                 }
182             }
183             // render list
184             if (log.isDebugEnabled())
185                 HtmlNavigationMenuRendererUtils.debugTree(log, facesContext, panelNav.getChildren(), 0);
186             renderListLayout(facesContext, panelNav);
187         }
188         else {
189             renderTableLayout(facesContext, panelNav);
190         }
191     }
192 
193     private void restoreOpenActiveStates(FacesContext facesContext,
194                                          HtmlPanelNavigationMenu panelNav, List children) {
195         for (int i = 0, size = children.size(); i < size; i++) {
196             UIComponent uiComponent = (UIComponent) children.get(i);
197             if (uiComponent instanceof HtmlCommandNavigationItem) {
198                 HtmlCommandNavigationItem prevItem = (HtmlCommandNavigationItem) uiComponent;
199                 if (prevItem.isOpen() || prevItem.isActive()) {
200                     HtmlCommandNavigationItem item = (HtmlCommandNavigationItem) panelNav.findComponent(uiComponent.getClientId(facesContext));
201                     if (item != null) {
202                         if (item.getActiveDirectly() != null && item.getActiveDirectly().booleanValue()) {
203                             item.setActive(prevItem.isActive());
204                         }
205                         else {
206                             copyValueBinding(prevItem, item, "active");
207                         }
208 
209                         if (item.getOpenDirectly() != null && item.getOpenDirectly().booleanValue()) {
210                             item.setOpen(prevItem.isOpen());
211                         }
212                         else {
213                             copyValueBinding(prevItem, item, "open");
214                         }
215                         if (!panelNav.isExpandAll() || prevItem.isActive())
216                             item.toggleOpen();
217                         if (prevItem.isOpen())
218                             restoreOpenActiveStates(facesContext, panelNav, prevItem.getChildren());
219                     }
220                 }
221             }
222         }
223     }
224 
225     private HtmlPanelNavigationMenu findPreviousPanelNav(FacesContext facesContext, HtmlPanelNavigationMenu panelNav) {
226         UIViewRoot previousViewRoot = findPreviousRoot(facesContext);
227         if (previousViewRoot != null) {
228             return (HtmlPanelNavigationMenu) previousViewRoot.findComponent(panelNav.getClientId(facesContext));
229         }
230         return null;
231     }
232 
233     private UIViewRoot findPreviousRoot(FacesContext facesContext) {
234         return (UIViewRoot) facesContext.getExternalContext().getRequestMap().get(HtmlPanelNavigationMenu.PREVIOUS_VIEW_ROOT);
235     }
236 
237     protected void renderListLayout(FacesContext facesContext, HtmlPanelNavigationMenu panelNav) throws IOException {
238         //if (panelNav.isRenderAll())
239         //    addResourcesToHeader(facesContext);
240 
241         ResponseWriter writer = facesContext.getResponseWriter();
242         if (panelNav.getChildCount() > 0) {
243             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
244             writer.startElement(HTML.UL_ELEM, panelNav);
245 
246             Map<String, List<ClientBehavior>> behaviors = panelNav.getClientBehaviors();
247             
248             if (behaviors != null && !behaviors.isEmpty())
249             {
250                 writer.writeAttribute(HTML.ID_ATTR, panelNav.getClientId(facesContext),null);
251                 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, panelNav, behaviors);
252                 HtmlRendererUtils.renderHTMLAttributes(writer, panelNav, HTML.UL_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS); 
253 
254             }
255             else
256             {
257                 HtmlRendererUtils.writeIdIfNecessary(writer, panelNav, facesContext);
258                 HtmlRendererUtils.renderHTMLAttributes(writer, panelNav, HTML.UL_PASSTHROUGH_ATTRIBUTES);
259             }
260 
261             //iterate over the tree and toggleOpen if viewId in item.getActiveOnVieIds()
262             activeOnViewId(panelNav, facesContext.getViewRoot().getViewId());
263             //iterate over the tree and set every item open if expandAll
264             if (panelNav.isExpandAll()) {
265                 expandAll(panelNav);
266             }
267 
268             HtmlNavigationMenuRendererUtils.renderChildrenListLayout(facesContext, writer, panelNav, panelNav.getChildren(), 0);
269 
270             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
271             writer.endElement(HTML.UL_ELEM);
272         }
273         else {
274             if (log.isWarnEnabled()) log.warn("PanelNavaigationMenu without children.");
275         }
276     }
277 
278     private void renderTableLayout(FacesContext facesContext, HtmlPanelNavigationMenu panelNav) throws IOException {
279         ResponseWriter writer = facesContext.getResponseWriter();
280 
281         if (panelNav.getChildCount() > 0) {
282             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
283             writer.startElement(HTML.TABLE_ELEM, panelNav);
284             Map<String, List<ClientBehavior>> behaviors = panelNav.getClientBehaviors();
285             
286             if (behaviors != null && !behaviors.isEmpty())
287             {
288                 writer.writeAttribute(HTML.ID_ATTR, panelNav.getClientId(facesContext),null);
289                 HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, panelNav, behaviors);
290                 HtmlRendererUtils.renderHTMLAttributes(writer, panelNav, HTML.TABLE_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS); 
291             }
292             else
293             {
294                 HtmlRendererUtils.writeIdIfNecessary(writer, panelNav, facesContext);
295                 HtmlRendererUtils.renderHTMLAttributes(writer, panelNav, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);                
296             }
297             if (panelNav.getStyle() == null && panelNav.getStyleClass() == null) {
298                 writer.writeAttribute(HTML.BORDER_ATTR, ZERO_INTEGER, null);
299             }
300 
301             HtmlNavigationMenuRendererUtils.renderChildrenTableLayout(facesContext, writer, panelNav, panelNav.getChildren(), 0);
302 
303             HtmlRendererUtils.writePrettyLineSeparator(facesContext);
304             writer.endElement(HTML.TABLE_ELEM);
305         }
306         else {
307             if (log.isWarnEnabled()) log.warn("PanelNavaigationMenu without children.");
308         }
309     }
310 
311     private void addResourcesToHeader(FacesContext context) {
312         //AddResource addResource = AddResourceFactory.getInstance(context);
313         //addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, HtmlPanelNavigationMenu.class, HORIZ_MENU_SCRIPT);
314         TomahawkResourceUtils.addOutputScriptResource(context,
315                 "oam.custom.navmenu.htmlnavmenu", HORIZ_MENU_SCRIPT);
316     }
317 
318     /**
319      * look for UINavigationMenuItem && UISelectItems & create components
320      */
321     private void preprocessNavigationItems(FacesContext facesContext, UIComponent parent,
322                                            List children, UniqueId uniqueId) {
323         for (int i = 0; i < children.size(); i++) {
324             UIComponent child = (UIComponent) children.get(i);
325 
326             if (child instanceof HtmlCommandNavigationItem) {
327                 HtmlCommandNavigationItem navMenuItem = (HtmlCommandNavigationItem) child;
328                 preprocessNavigationItems(facesContext, navMenuItem, navMenuItem.getChildren(), uniqueId);
329             }
330             else if (child instanceof UINavigationMenuItem) {
331                 UINavigationMenuItem uiNavMenuItem = (UINavigationMenuItem) child;
332                 createHtmlCommandNavigationItem(facesContext, parent, i, uiNavMenuItem, uniqueId);
333             }
334             else if (child instanceof UISelectItems) {
335                 List list = new ArrayList();
336                 if (child.getId() == null) {
337                     child.setId("testit");
338                 }
339                 NavigationMenuUtils.addNavigationMenuItems((UISelectItems) child, list);
340                 addUINavigationMenuItems(facesContext, parent, children, i + 1, list);
341             }
342         }
343     }
344 
345     private void addUINavigationMenuItems(FacesContext facesContext, UIComponent parent, List children, int startIndex, List menuItems) {
346         String clientId = parent.getClientId(facesContext);
347         clientId = clientId.replaceAll(":", "_");
348         for (int j = 0, sizej = menuItems.size(); j < sizej; j++) {
349             NavigationMenuItem navigationMenuItem = (NavigationMenuItem) menuItems.get(j);
350             UINavigationMenuItem uiNavigationMenuItem =
351                 (UINavigationMenuItem) facesContext.getApplication().createComponent(UINavigationMenuItem.COMPONENT_TYPE);
352             uiNavigationMenuItem.setId(clientId + "_uinavmitem" + (startIndex + j));
353             uiNavigationMenuItem.getClientId(facesContext); // create clientid
354             children.add(startIndex++, uiNavigationMenuItem);
355             uiNavigationMenuItem.setParent(parent);
356             if (navigationMenuItem.getAction() != null) {
357                 uiNavigationMenuItem.setAction(HtmlNavigationMenuRendererUtils.getMethodBinding(facesContext, navigationMenuItem.getAction(), false));
358             }
359             if (navigationMenuItem.getActionListener() != null) {
360                 uiNavigationMenuItem.setActionListener(HtmlNavigationMenuRendererUtils.getMethodBinding(facesContext,
361                                                                                                         navigationMenuItem.getActionListener(), true));
362             }
363             uiNavigationMenuItem.setIcon(navigationMenuItem.getIcon());
364             uiNavigationMenuItem.setRendered(navigationMenuItem.isRendered());
365             uiNavigationMenuItem.setActiveOnViewIds(navigationMenuItem.getActiveOnViewIds());
366             uiNavigationMenuItem.setSplit(navigationMenuItem.isSplit());
367             uiNavigationMenuItem.setItemLabel(navigationMenuItem.getLabel());
368             uiNavigationMenuItem.setOpen(navigationMenuItem.isOpen());
369             uiNavigationMenuItem.setActive(navigationMenuItem.isActive());
370             uiNavigationMenuItem.setValue(navigationMenuItem.getValue());
371             HtmlNavigationMenuRendererUtils.setAttributeValue(facesContext, uiNavigationMenuItem,
372                                                               "externalLink", navigationMenuItem.getExternalLink());
373             //uiNavigationMenuItem.setExternalLink(navigationMenuItem.getExternalLink());
374             uiNavigationMenuItem.setTransient(false);
375             uiNavigationMenuItem.setTarget(navigationMenuItem.getTarget());
376             uiNavigationMenuItem.setDisabled(navigationMenuItem.isDisabled());
377             uiNavigationMenuItem.setDisabledStyle(navigationMenuItem.getDisabledStyle());
378             uiNavigationMenuItem.setDisabledStyleClass(navigationMenuItem.getDisabledStyleClass());
379 
380             if (navigationMenuItem.getNavigationMenuItems() != null && navigationMenuItem.getNavigationMenuItems().length > 0)
381             {
382                 addUINavigationMenuItems(facesContext, uiNavigationMenuItem, uiNavigationMenuItem.getChildren(), 0,
383                                          Arrays.asList(navigationMenuItem.getNavigationMenuItems()));
384             }
385         }
386     }
387 
388     private HtmlPanelNavigationMenu getParentPanelNavigation(UIComponent uiComponent) {
389         if (uiComponent instanceof HtmlPanelNavigationMenu) {
390             return (HtmlPanelNavigationMenu) uiComponent;
391         }
392         UIComponent parent = uiComponent.getParent();
393 
394         // search HtmlPanelNavigation
395         UIComponent p = parent;
396         while (p != null && !(p instanceof HtmlPanelNavigationMenu)) {
397             p = p.getParent();
398         }
399         // p is now the HtmlPanelNavigation
400         if (p == null) {
401             log.error("HtmlCommandNavigation without parent HtmlPanelNavigation ?!");
402             return null;
403         }
404         return (HtmlPanelNavigationMenu) p;
405     }
406 
407     private void createHtmlCommandNavigationItem(FacesContext facesContext, UIComponent parent, int i,
408                                                  UINavigationMenuItem uiNavMenuItem, UniqueId uniqueId) {
409         HtmlPanelNavigationMenu menu = getParentPanelNavigation(parent);
410         // Create HtmlCommandNavigationItem
411         HtmlCommandNavigationItem newItem = (HtmlCommandNavigationItem)
412             facesContext.getApplication().createComponent(HtmlCommandNavigationItem.COMPONENT_TYPE);
413         String parentId = parent.getClientId(facesContext);
414         parentId = parentId.replaceAll(":", "_");
415         int id = uniqueId.next();
416         newItem.setId(parentId + "_item" + id);
417         newItem.getClientId(facesContext); // create clientid
418         newItem.setRendererType(RENDERER_TYPE);
419         parent.getChildren().add(i + 1, newItem);
420         newItem.setParent(parent);
421         // set action & actionListner
422         newItem.setAction(uiNavMenuItem.getAction());
423         newItem.setActionListener(uiNavMenuItem.getActionListener());
424         ActionListener[] listeners = uiNavMenuItem.getActionListeners();
425         for (int j = 0; j < listeners.length; j++) {
426             newItem.addActionListener(listeners[j]);
427         }
428         // value
429         newItem.setValue(uiNavMenuItem.getValue());
430         // immeditate
431         if (!copyValueBinding(uiNavMenuItem, newItem, "immediate"))
432             newItem.setImmediate(uiNavMenuItem.isImmediate());
433         // transient, rendered
434         if (!copyValueBinding(uiNavMenuItem, newItem, "transient"))
435             newItem.setTransient(uiNavMenuItem.isTransient());
436         if (!copyValueBinding(uiNavMenuItem, newItem, "rendered"))
437             newItem.setRendered(uiNavMenuItem.isRendered());
438         if (!copyValueBinding(uiNavMenuItem, newItem, "externalLink"))
439             newItem.setExternalLink(uiNavMenuItem.getExternalLink());
440         if (!copyValueBinding(uiNavMenuItem, newItem, "activeOnViewIds"))
441             newItem.setActiveOnViewIds(uiNavMenuItem.getActiveOnViewIds());
442 
443         if (uiNavMenuItem.isOpen() && ! menu.isExpandAll())
444             newItem.toggleOpen();
445 
446         if (uiNavMenuItem.getActiveDirectly() != null) {
447             newItem.setActive(uiNavMenuItem.isActive());
448         }
449         else {
450             newItem.setValueBinding("active", uiNavMenuItem.getValueBinding("active"));
451         }
452 
453         if (!copyValueBinding(uiNavMenuItem, newItem, "target"))
454             newItem.setTarget(uiNavMenuItem.getTarget());
455         if (!copyValueBinding(uiNavMenuItem, newItem, "disabled"))
456             newItem.setDisabled(uiNavMenuItem.isDisabled());
457         if (!copyValueBinding(uiNavMenuItem, newItem, "disabledStyle"))
458             newItem.setDisabledStyle(uiNavMenuItem.getDisabledStyle());
459         if (!copyValueBinding(uiNavMenuItem, newItem, "disabledStyleClass"))
460             newItem.setDisabledStyleClass(uiNavMenuItem.getDisabledStyleClass());
461 
462         if (uiNavMenuItem.getActiveOnViewIdsDirectly() != null) {
463             newItem.setActiveOnViewIds(uiNavMenuItem.getActiveOnViewIdsDirectly());
464         }
465 
466         // If the parent-Element is disabled the child is disabled as well
467         if (parent instanceof HtmlPanelNavigationMenu) {
468             if (newItem.getDisabledStyle() == null) {
469                 newItem.setDisabledStyle(
470                     ((HtmlPanelNavigationMenu) parent).getDisabledStyle()
471                 );
472             }
473             if (newItem.getDisabledStyleClass() == null) {
474                 newItem.setDisabledStyleClass(
475                     ((HtmlPanelNavigationMenu) parent).getDisabledStyleClass()
476                 );
477             }
478             if (((HtmlPanelNavigationMenu) parent).isDisabled()) {
479                 newItem.setDisabled(true);
480             }
481         }
482         if (parent instanceof HtmlCommandNavigationItem) {
483             if (newItem.getDisabledStyle() == null) {
484                 newItem.setDisabledStyle(
485                     ((HtmlCommandNavigationItem) parent).getDisabledStyle()
486                 );
487             }
488             if (newItem.getDisabledStyleClass() == null) {
489                 newItem.setDisabledStyleClass(
490                     ((HtmlCommandNavigationItem) parent).getDisabledStyleClass()
491                 );
492             }
493             if (((HtmlCommandNavigationItem) parent).isDisabled()) {
494                 newItem.setDisabled(true);
495             }
496         }
497 
498         if (uiNavMenuItem.getIcon() != null) {
499             UIGraphic uiGraphic = (UIGraphic) facesContext.getApplication().createComponent(UIGraphic.COMPONENT_TYPE);
500             uiGraphic.setId(parentId + "_img" + id);
501             uiGraphic.getClientId(facesContext);
502             newItem.getChildren().add(uiGraphic);
503             uiGraphic.setParent(newItem);
504             if (NavigationMenuUtils.isValueReference(uiNavMenuItem.getIcon())) {
505                 uiGraphic.setValueBinding("value",
506                                           facesContext.getApplication().createValueBinding(uiNavMenuItem.getIcon()));
507             }
508             else {
509                 uiGraphic.setValue(uiNavMenuItem.getIcon());
510             }
511         }
512 
513         else {
514             // Create and add UIOutput
515             UIOutput uiOutput = (UIOutput) facesContext.getApplication().createComponent(UIOutput.COMPONENT_TYPE);
516             uiOutput.setId(parentId + "_txt" + id);
517             uiOutput.getClientId(facesContext); // create clientid
518             newItem.getChildren().add(uiOutput);
519             uiOutput.setParent(newItem);
520             if (uiNavMenuItem.getItemLabel() != null) {
521                 if (NavigationMenuUtils.isValueReference(uiNavMenuItem.getItemLabel())) {
522                     uiOutput.setValueBinding("value",
523                                              facesContext.getApplication().createValueBinding(uiNavMenuItem.getItemLabel()));
524                 }
525                 else {
526                     uiOutput.setValue(uiNavMenuItem.getItemLabel());
527                 }
528             }
529             else {
530                 Object value = uiNavMenuItem.getValue();
531                 if (value != null &&
532                     NavigationMenuUtils.isValueReference(value.toString())) {
533                     uiOutput.setValueBinding("value",
534                                              facesContext.getApplication().createValueBinding(value.toString()));
535                 }
536                 else {
537                     uiOutput.setValue(uiNavMenuItem.getValue());
538                 }
539             }
540         }
541         // process next level
542         log.debug("Instance of UINavigationMenuItem, preprocess childrens");
543         preprocessNavigationItems(facesContext, newItem, uiNavMenuItem.getChildren(), uniqueId);
544     }
545 
546     private boolean copyValueBinding(UIComponent source, UIComponent target, String binding) {
547         ValueBinding valueBinding = source.getValueBinding(binding);
548         if (valueBinding == null)
549             return false;
550         target.setValueBinding(binding, valueBinding);
551         return true;
552     }
553 
554 // protected
555 
556     protected String getStyle(FacesContext facesContext, UIComponent link) {
557         if (!(link instanceof HtmlCommandNavigationItem)) {
558             throw new IllegalArgumentException("expected instance of " + HtmlCommandNavigationItem.class.getName());
559         }
560 
561         UIComponent navPanel = HtmlNavigationMenuRendererUtils.getPanel(link);
562 
563         HtmlCommandNavigationItem navItem = (HtmlCommandNavigationItem) link;
564         if (navItem.isActive()) {
565             return ((HtmlPanelNavigationMenu) navPanel).getActiveItemStyle();
566         }
567         else if (navItem.isOpen()) {
568             return ((HtmlPanelNavigationMenu) navPanel).getOpenItemStyle();
569         }
570         else {
571             return ((HtmlPanelNavigationMenu) navPanel).getItemStyle();
572         }
573     }
574 
575     protected String getStyleClass(FacesContext facesContext, UIComponent link) {
576         if (!(link instanceof HtmlCommandNavigationItem)) {
577             throw new IllegalArgumentException();
578         }
579 
580         UIComponent navPanel = HtmlNavigationMenuRendererUtils.getPanel(link);
581 
582         HtmlCommandNavigationItem navItem = (HtmlCommandNavigationItem) link;
583         if (navItem.isActive()) {
584             return ((HtmlPanelNavigationMenu) navPanel).getActiveItemClass();
585         }
586         else if (navItem.isOpen()) {
587             return ((HtmlPanelNavigationMenu) navPanel).getOpenItemClass();
588         }
589         else {
590             return ((HtmlPanelNavigationMenu) navPanel).getItemClass();
591         }
592     }
593 
594     private static class UniqueId {
595         private int _id;
596 
597         public int next() {
598             return _id++;
599         }
600 
601         public void decrease() {
602             _id--;
603         }
604     }
605 
606     private void expandAll(UIComponent parent) {
607         //Recurse over all Children setOpen if child is HtmlCommandNavigationItem
608         if (parent instanceof HtmlCommandNavigationItem) {
609             HtmlCommandNavigationItem navItem = (HtmlCommandNavigationItem) parent;
610             navItem.setOpen(true);
611         }
612         List children = parent.getChildren();
613         UIComponent child;
614         for (int i = 0; i < children.size(); i++) {
615             child = (UIComponent) children.get(i);
616             expandAll(child);
617         }
618     }
619 
620     private void activeOnViewId(UIComponent parent, String viewId) {
621         //Recurse over all Children setOpen if child is HtmlCommandNavigationItem
622         if (parent instanceof HtmlCommandNavigationItem) {
623             HtmlCommandNavigationItem navItem = (HtmlCommandNavigationItem) parent;
624             String[] viewIds = navItem.getActiveOnVieIds();
625             for (int i = 0; i < viewIds.length; i++) {
626                 if (viewId.equals(viewIds[i])) {
627                     navItem.toggleOpen();
628                     navItem.setActive(true);
629                     return;
630                 }
631             }
632             ;
633         }
634         List children = parent.getChildren();
635         UIComponent child;
636         for (int i = 0; i < children.size(); i++) {
637             child = (UIComponent) children.get(i);
638             activeOnViewId(child, viewId);
639         }
640     }
641 }