class SubnavTag extends BodyTagSupport {

    private String css;
    private String currentcss;

    /**
     * Returns the value of the CSS class to be used for tab decoration. If not set will return a blank string.
     * @return the CSS for the tab
     */
    public String getCss() {
        return clean(css);
    }

    /**
     * Sets the CSS used for tab decoration.
     * @param css The CSS for the tab
     */
    public void setCss(String css) {
        this.css = css;
    }

    /**
     * Returns the value of the CSS class to be used for the currently selected LI (tab). If not set will
     * return a blank string.
     * @return the CSS class
     */
    public String getCurrentcss() {
        return clean(currentcss);
    }

    /**
     * Sets the CSS class value for the currently selected tab.
     * @param currentcss the CSS class
     */
    public void setCurrentcss(String currentcss) {
        this.currentcss = currentcss;
    }

    /**
     * Does nothing, returns {@link #EVAL_BODY_BUFFERED} always.
     */
    @Override
    public int doStartTag() throws JspException {
        return EVAL_BODY_BUFFERED;
    }

    /**
     * Gets the {@link AdminPageBean} instance from the request. If it doesn't exist then execution is stopped
     * and nothing is printed. If it exists, retrieve values from it and render the sidebar items. The body content
     * of the tag is assumed to have an A tag in it with tokens to replace (see class description) as well
     * as having a subsidebar tag..
     *
     * @return {@link #EVAL_PAGE} after rendering the tabs.
     * @throws JspException if an exception occurs while rendering the sidebar items.
     */
    @Override
    public int doEndTag() throws JspException {<FILL_FUNCTION_BODY>}

    /**
     * Cleans the given string - if it's null, it's converted to a blank string. If it has ' then those are
     * converted to double ' so HTML isn't screwed up.
     *
     * @param in the string to clean
     * @return a cleaned version - not null and with escaped characters.
     */
    private String clean(String in) {
        return (in == null ? "" : in.replaceAll("'", "\\'"));
    }
}

        // Start by getting the request from the page context
        HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();

        // Check for body of this tag and the child tag
        if (getBodyContent().getString() == null) {
            throw new JspException("Error, no template (body value) set for the sidebar tag.");
        }

        // Get the initial subpage and page IDs
        String subPageID = (String)request.getAttribute("subPageID");
        String pageID = (String)request.getAttribute("pageID");

        // If the pageID is null, use the subPageID to set it. If both the pageID and
        // subPageIDs are null, return because these are key to execution of the tag.
        if (subPageID != null || pageID != null) {

            if (pageID == null) {
                Element subPage = AdminConsole.getElemnetByID(subPageID);
                pageID = subPage.getParent().getParent().attributeValue("id");
            }

            // Top level menu items
            if (AdminConsole.getModel().elements().size() > 0) {
                JspWriter out = pageContext.getOut();
                StringBuilder buf = new StringBuilder();

                Element current = null;
                Element subcurrent = null;
                Element subnav = null;
                if (subPageID != null) {
                    subcurrent = AdminConsole.getElemnetByID(subPageID);
                }
                current = AdminConsole.getElemnetByID(pageID);
                if (current != null) {
                    if (subcurrent != null) {
                        subnav = subcurrent.getParent().getParent().getParent();
                    }
                    else {
                        subnav = current.getParent();
                    }
                }

                Element currentTab = (Element)AdminConsole.getModel().selectSingleNode(
                        "//*[@id='" + pageID + "']/ancestor::tab");

                // Loop through all items in the root, print them out
                if (currentTab != null) {
                    Collection items = currentTab.elements();
                    if (items.size() > 0) {
                        buf.append("<ul>");
                        for (Object itemObj : items) {
                            Element item = (Element) itemObj;
                            if (item.elements().size() > 0) {
                                Element firstSubItem = (Element)item.elements().get(0);
                                String pluginName = item.attributeValue("plugin");
                                String subitemID = item.attributeValue("id");
                                String subitemName = item.attributeValue("name");
                                String subitemURL = firstSubItem.attributeValue("url");
                                String subitemDescr = item.attributeValue("description");
                                String value = getBodyContent().getString();
                                if (value != null) {
                                    value = value.replaceAll("\\[id]", clean(subitemID));
                                    value = value.replaceAll("\\[name]", clean(AdminConsole.getAdminText(subitemName, pluginName)));
                                    value = value.replaceAll("\\[description]", clean(AdminConsole.getAdminText(subitemDescr, pluginName)));
                                    value = value.replaceAll("\\[url]",request.getContextPath() + "/" + clean(subitemURL));
                                }
                                String css = getCss();
                                boolean isCurrent = subnav != null && item.equals(subnav);
                                if (isCurrent) {
                                    css = getCurrentcss();
                                }
                                buf.append("<li class=\"").append(css).append("\">").append(value).append("</li>");
                            }
                        }
                        buf.append("</ul>");
                        try {
                            out.write(buf.toString());
                        }
                        catch (IOException e) {
                            throw new JspException(e);
                        }
                    }
                }
            }
        }
        return EVAL_PAGE;
    
<no_super_class>