Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.myfaces.custom.navmenu.htmlnavmenu; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.myfaces.custom.navmenu.NavigationMenuUtils; import org.apache.myfaces.custom.navmenu.UINavigationMenuItem; import org.apache.myfaces.shared_tomahawk.el.SimpleActionMethodBinding; import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils; import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML; import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils; import javax.faces.component.UIComponent; import javax.faces.component.UIOutput; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.el.MethodBinding; import javax.faces.el.ValueBinding; import javax.faces.event.ActionEvent; import java.io.IOException; import java.util.Iterator; import java.util.List; /** * @author Thomas Spiegl * @author Manfred Geiler */ class HtmlNavigationMenuRendererUtils { private static final Log log = LogFactory.getLog(HtmlNavigationMenuRendererUtils.class); private static final Class[] ACTION_LISTENER_ARGS = { ActionEvent.class }; private HtmlNavigationMenuRendererUtils() { } public static void renderChildrenListLayout(FacesContext facesContext, ResponseWriter writer, HtmlPanelNavigationMenu panelNav, List children, int level) throws IOException { for (Iterator it = children.iterator(); it.hasNext();) { UIComponent child = (UIComponent) it.next(); if (!child.isRendered()) continue; if (child instanceof UINavigationMenuItem) { renderChildrenListLayout(facesContext, writer, panelNav, child.getChildren(), level); } if (child instanceof HtmlCommandNavigationItem) { //navigation item HtmlRendererUtils.writePrettyLineSeparator(facesContext); HtmlCommandNavigationItem navItem = (HtmlCommandNavigationItem) child; String externalLink = navItem.getExternalLink(); String style = HtmlNavigationMenuRendererUtils.getNavigationItemStyle(panelNav, navItem); String styleClass = HtmlNavigationMenuRendererUtils.getNavigationItemClass(panelNav, navItem); writer.startElement(HTML.LI_ELEM, panelNav); HtmlNavigationMenuRendererUtils.writeStyleAttributes(writer, style, styleClass); Object value = navItem.getValue(); boolean renderAsOutputLink = externalLink != null && value != null; if (!renderAsOutputLink) { //if there is an external link specified don't render the command nav item, its content //will be wrapped by a output link in the renderChildren() method if (externalLink == null) { navItem.setValue(null); // unset value, value must not be rendered navItem.encodeBegin(facesContext); } HtmlNavigationMenuRendererUtils.renderChildren(facesContext, navItem, panelNav); if (externalLink == null) { navItem.encodeEnd(facesContext); navItem.setValue(value); // restore value } } else { //there is an external link value and display value exists, so, just render its children renderChildren(facesContext, navItem, panelNav); } if (hasCommandNavigationItemChildren(navItem)) { writer.startElement(HTML.UL_ELEM, panelNav); if (panelNav.isRenderAll()) HtmlNavigationMenuRendererUtils.writeStyleAttributes(writer, navItem.getStyle(), navItem.getStyleClass()); HtmlRendererUtils.renderHTMLAttributes(writer, panelNav, HTML.UL_PASSTHROUGH_ATTRIBUTES); renderChildrenListLayout(facesContext, writer, panelNav, child.getChildren(), level + 1); writer.endElement(HTML.UL_ELEM); } writer.endElement(HTML.LI_ELEM); } } } private static boolean hasCommandNavigationItemChildren(HtmlCommandNavigationItem item) { List children = item.getChildren(); for (int i = 0, sizei = children.size(); i < sizei; i++) { if (children.get(i) instanceof HtmlCommandNavigationItem) { return true; } } return false; } public static void renderChildrenTableLayout(FacesContext facesContext, ResponseWriter writer, HtmlPanelNavigationMenu panelNav, List children, int level) throws IOException { for (Iterator it = children.iterator(); it.hasNext();) { UIComponent child = (UIComponent) it.next(); if (!child.isRendered()) continue; if (child instanceof HtmlCommandNavigationItem) { //navigation item HtmlRendererUtils.writePrettyLineSeparator(facesContext); String style = getNavigationItemStyle(panelNav, (HtmlCommandNavigationItem) child); String styleClass = getNavigationItemClass(panelNav, (HtmlCommandNavigationItem) child); writer.startElement(HTML.TR_ELEM, panelNav); writer.startElement(HTML.TD_ELEM, panelNav); writeStyleAttributes(writer, style, styleClass); if (style != null || styleClass != null) { writer.startElement(HTML.SPAN_ELEM, panelNav); writeStyleAttributes(writer, style, styleClass); } indent(writer, level); child.encodeBegin(facesContext); child.encodeEnd(facesContext); if (style != null || styleClass != null) { writer.endElement(HTML.SPAN_ELEM); } writer.endElement(HTML.TD_ELEM); writer.endElement(HTML.TR_ELEM); if (child.getChildCount() > 0) { renderChildrenTableLayout(facesContext, writer, panelNav, child.getChildren(), level + 1); } } else { //separator HtmlRendererUtils.writePrettyLineSeparator(facesContext); String style = panelNav.getSeparatorStyle(); String styleClass = panelNav.getSeparatorClass(); writer.startElement(HTML.TR_ELEM, panelNav); writer.startElement(HTML.TD_ELEM, panelNav); writeStyleAttributes(writer, style, styleClass); if (style != null || styleClass != null) { writer.startElement(HTML.SPAN_ELEM, panelNav); writeStyleAttributes(writer, style, styleClass); } indent(writer, level); RendererUtils.renderChild(facesContext, child); if (style != null || styleClass != null) { writer.endElement(HTML.SPAN_ELEM); } writer.endElement(HTML.TD_ELEM); writer.endElement(HTML.TR_ELEM); } } } public static void indent(ResponseWriter writer, int level) throws IOException { StringBuffer buf = new StringBuffer(); for (int i = 0; i < level; i++) { buf.append("    "); } writer.write(buf.toString()); } public static String getNavigationItemStyle(HtmlPanelNavigationMenu navPanel, HtmlCommandNavigationItem navItem) { if (navItem.isActive()) { return navPanel.getActiveItemStyle(); } else if (navItem.isOpen()) { return navPanel.getOpenItemStyle(); } else { return navPanel.getItemStyle(); } } public static String getNavigationItemClass(HtmlPanelNavigationMenu navPanel, HtmlCommandNavigationItem navItem) { // MYFACES-117, if a styleClass is supplied for a HtmlCommandNavigationItem, // panelNavigation active/open/normal styles for items will be overriden if (navItem.getStyleClass() != null) { return navItem.getStyleClass(); } if (navItem.isActive()) { return navPanel.getActiveItemClass(); } else if (navItem.isOpen()) { return navPanel.getOpenItemClass(); } else { return navPanel.getItemClass(); } } public static void writeStyleAttributes(ResponseWriter writer, String style, String styleClass) throws IOException { HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR, style); HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR, styleClass); } public static UIComponent getPanel(UIComponent link) { UIComponent navPanel = link.getParent(); while (navPanel != null && !(navPanel instanceof HtmlPanelNavigationMenu)) { navPanel = navPanel.getParent(); } if (navPanel == null) { throw new IllegalStateException("HtmlCommandNavigationItem not nested in HtmlPanelNavigation!?"); } return navPanel; } public static boolean isListLayout(HtmlPanelNavigationMenu panelNav) { return !"Table".equalsIgnoreCase(panelNav.getLayout()); } public static void renderChildren(FacesContext facesContext, HtmlCommandNavigationItem component, HtmlPanelNavigationMenu parentPanelNav) throws IOException { if (component.getChildCount() > 0) { //if there is an external link value, wrapp the content with an output link if (component.getExternalLink() != null) { ResponseWriter writer = facesContext.getResponseWriter(); writer.startElement(HTML.ANCHOR_ELEM, null); writer.writeAttribute(HTML.HREF_ATTR, component.getExternalLink(), null); if (component.getTarget() != null) writer.writeAttribute(HTML.TARGET_ATTR, component.getTarget(), null); //the style attributes need to be taken from the parent panel nav, because the command panel navigation item //is not rendered in this case which would have render them String style = HtmlNavigationMenuRendererUtils.getNavigationItemStyle(parentPanelNav, component); String styleClass = HtmlNavigationMenuRendererUtils.getNavigationItemClass(parentPanelNav, component); HtmlNavigationMenuRendererUtils.writeStyleAttributes(writer, style, styleClass); } for (Iterator it = component.getChildren().iterator(); it.hasNext();) { UIComponent child = (UIComponent) it.next(); if (!(child instanceof HtmlCommandNavigationItem)) { RendererUtils.renderChild(facesContext, child); } } //end wrapper output link if (component.getExternalLink() != null) { ResponseWriter writer = facesContext.getResponseWriter(); writer.endElement(HTML.ANCHOR_ELEM); } } } public static void debugTree(Log log, FacesContext facesContext, List children, int level) { for (Iterator it = children.iterator(); it.hasNext();) { UIComponent child = (UIComponent) it.next(); if (child instanceof UINavigationMenuItem) { UINavigationMenuItem item = (UINavigationMenuItem) child; StringBuffer buf = new StringBuffer(); for (int i = 0; i < level * 4; i++) buf.append(' '); log.debug(buf.toString() + "--> " + item.getItemLabel() + " id:" + item.getClientId(facesContext)); debugTree(log, facesContext, child.getChildren(), level + 1); } else if (child instanceof HtmlCommandNavigationItem) { HtmlCommandNavigationItem item = (HtmlCommandNavigationItem) child; StringBuffer buf = new StringBuffer(); for (int i = 0; i < level * 4; i++) buf.append(' '); String value; if (item.getChildren().size() > 0 && item.getChildren().get(0) instanceof UIOutput) { UIOutput uiOutput = (UIOutput) item.getChildren().get(0); value = uiOutput.getValue() != null ? uiOutput.getValue().toString() : "?"; } else { value = item.getValue() != null ? item.getValue().toString() : ""; } log.debug(buf.toString() + value + " id:" + item.getClientId(facesContext)); debugTree(log, facesContext, child.getChildren(), level + 1); } } } public static HtmlCommandNavigationItem findPreviousItem(UIViewRoot previousViewRoot, String clientId) { HtmlCommandNavigationItem previousItem = null; if (previousViewRoot != null) { UIComponent previousComp = previousViewRoot.findComponent(clientId); if (previousComp instanceof HtmlCommandNavigationItem) { previousItem = (HtmlCommandNavigationItem) previousComp; } } return previousItem; } public static MethodBinding getMethodBinding(FacesContext facesContext, String value, boolean actionListener) { MethodBinding mb; if (NavigationMenuUtils.isValueReference(value)) { mb = facesContext.getApplication().createMethodBinding(value, actionListener ? ACTION_LISTENER_ARGS : null); } else { if (actionListener) { log.error("Invalid actionListener value " + value + " (has to be ValueReference!)"); mb = null; } else { mb = new SimpleActionMethodBinding(value); } } return mb; } public static void setAttributeValue(FacesContext facesContext, UIComponent comp, String attribute, String value) { if (value == null) return; if (NavigationMenuUtils.isValueReference(value)) { ValueBinding vb = facesContext.getApplication().createValueBinding(value); comp.setValueBinding(attribute, vb); } else { comp.getAttributes().put(attribute, value); } } }