You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@click.apache.org by sa...@apache.org on 2010/04/11 09:39:15 UTC
svn commit: r932847 - in
/click/trunk/click/extras/src/org/apache/click/extras/control: Menu.java
MenuFactory.java
Author: sabob
Date: Sun Apr 11 07:39:15 2010
New Revision: 932847
URL: http://svn.apache.org/viewvc?rev=932847&view=rev
Log:
javadoc
Modified:
click/trunk/click/extras/src/org/apache/click/extras/control/Menu.java
click/trunk/click/extras/src/org/apache/click/extras/control/MenuFactory.java
Modified: click/trunk/click/extras/src/org/apache/click/extras/control/Menu.java
URL: http://svn.apache.org/viewvc/click/trunk/click/extras/src/org/apache/click/extras/control/Menu.java?rev=932847&r1=932846&r2=932847&view=diff
==============================================================================
--- click/trunk/click/extras/src/org/apache/click/extras/control/Menu.java (original)
+++ click/trunk/click/extras/src/org/apache/click/extras/control/Menu.java Sun Apr 11 07:39:15 2010
@@ -54,11 +54,13 @@ import org.w3c.dom.NodeList;
* </tr>
* </table>
*
- * Application menus are defined using a <tt>/WEB-INF</tt> configuration
- * file located under the <tt>/WEB-INF</tt> directory or the root classpath.
- * An example Menu configuration files is provided below.
+ * <h3><a name="configuration"></a>Configuration</h3>
*
- * <pre class="codeConfig">
+ * Application menus are normally defined using a configuration file
+ * (<tt>menu.xml</tt> by default) located under the <tt>/WEB-INF</tt> directory
+ * or the root classpath. An example Menu configuration file is provided below.
+ *
+ * <pre class="prettyprint">
* <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
* <menu>
* <menu label="Home" path="user/home.htm" roles="tomcat, role1"/>
@@ -72,16 +74,18 @@ import org.w3c.dom.NodeList;
* </menu>
* </menu> </pre>
*
- * To include the root menu item in your page, simply use the default Menu constructor:
+ * Use a {@link MenuFactory} to load the Menu items and include the root menu
+ * item in your page:
*
* <pre class="prettyprint">
* public class BorderPage extends Page {
*
- * @Bindable public Menu rootMenu;
+ * private Menu rootMenu;
*
* public BorderPage() {
* MenuFactory menuFactory = new MenuFactory();
* rootMenu = menuFactory.getRootMenu();
+ * addControl(rootMenu);
* }
*
* @Override
@@ -91,8 +95,65 @@ import org.w3c.dom.NodeList;
*
* } </pre>
*
- * To render the configured Menu hierarchy you will need to use a Velocity
- * #macro or Velocity code in your page. For example:
+ * <h3><a name="programmatic"></a>Programmatically defined menus</h3>
+ *
+ * It is also possible to create Menus programmatically, for example:
+ *
+ * <pre class="prettyprint">
+ * public class BorderPage extends Page {
+ *
+ * private static class Menu rootMenu;
+ *
+ * public BorderPage() {
+ *
+ * if (rootMenu == null) {
+ * rootMenu = new MenuBuilder().buildMenu();
+ * }
+ *
+ * addControl(rootMenu);
+ * }
+ * } </pre>
+ *
+ * <pre class="prettyprint">
+ * public class MenuBuilder() {
+ *
+ * public Menu buildMenu() {
+ *
+ * Menu rootMenu = new Menu("rootMenu");
+ * rootMenu.add(createMenu("Home", "home.htm"));
+ *
+ * Menu customerMenu = createMenu("Home", "home.htm");
+ * rootMenu.add(customerMenu);
+ *
+ * customerMenu.add(createMenu("Search Customers", "search-customers.htm"));
+ * customerMenu.add(createMenu("Edit Customer", "edit-customer.htm"));
+ *
+ * ...
+ *
+ * return rootMenu;
+ * }
+ *
+ * private Menu createMenu(String label, String path) {
+ * Menu menu = new Menu();
+ * menu.setLabel(label);
+ * menu.setPath(path);
+ * menu.setTitle(label);
+ * return menu;
+ * }
+ * }</pre>
+ *
+ * <h3><a name="rendering"></a>Rendering</h3>
+ *
+ * To render the configured Menu hierarchy you can reference the root menu by
+ * its name in the Velocity template. For example:
+ * <pre class="codeHtml">
+ * <span class="st">$rootMenu</span> </pre>
+ *
+ * The hierarchical Menu structure is rendered as an HTML list: <ul>.
+ * <p/>
+ *
+ * Alternatively, you can render the menu using a Velocity #macro or Velocity
+ * code in your template. For example:
*
* <pre class="codeHtml">
* <span class="red">#</span>writeMenu(<span class="st">$rootMenu</span>) </pre>
@@ -140,21 +201,21 @@ import org.w3c.dom.NodeList;
* <span class="red">#end</span> </pre>
*
* This example uses role path based security to only display the menu items
- * the user is authorized to see. If you not using this security feature in your
- * application you should remove the macro {@link #isUserInRoles()} checks so
+ * the user is authorized to see. If you are not using this security feature in
+ * your application you should remove the macro {@link #isUserInRoles()} checks so
* the menu items will be rendered.
* <p/>
* Note individual menu items will render themselves as simple anchor tags using
* their {@link #toString()} method. For more fine grain control you should
* extend your Velocity macro to render individual menu items.
*
- * <h3>Security</h3>
+ * <h3><a name="security"></a>Security</h3>
*
* Menus support role based security via the {@link #isUserInRoles()}
* method. When creating secure menus define the valid roles in the menu items.
* For example:
*
- * <pre class="codeConfig">
+ * <pre class="prettyprint">
* <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
* <menu>
* <menu label="Home" path="user/home.htm" roles="user,admin">
@@ -170,10 +231,10 @@ import org.w3c.dom.NodeList;
* {@link AccessController} interface. The default AccessController is provided
* by the {@link RoleAccessController} which uses the JEE container is user in
* role facility. By providing your own AccessController you can have menu
- * access control using other security frameworks such as JSecurity or Spring
- * Security (Acegi).
+ * access control using other security frameworks such as Spring
+ * Security (Acegi) or Apache Shiro.
*
- * <h3>Menu Configuration DTD</h3>
+ * <h3><a name="config-dtd"></a>Menu Configuration DTD</h3>
*
* The Menu config file DTD is provided below:
*
@@ -192,8 +253,19 @@ import org.w3c.dom.NodeList;
* <!ATTLIST <span class="red">menu</span> <span class="st">roles</span> CDATA #IMPLIED>
* <!ATTLIST <span class="red">menu</span> <span class="st">pages</span> CDATA #IMPLIED> </pre>
*
- * <a name="resources"></a>
- * <h3>CSS and JavaScript resources</h3>
+ * The Menu DTD is also published online at
+ * <a href="http://click.apache.org/dtds/menu-2.2.dtd">http://click.apache.org/dtds/menu-2.2.dtd</a>.
+ *
+ * <h3><a name="message-resources"></a>Message Resources and Internationalization (i18n)</h3>
+ *
+ * Menus automatically pick up localized messages where applicable. Please see
+ * the following methods on how to customize these messages:
+ * <ul>
+ * <li>{@link #getLabel()}</li>
+ * <li>{@link #getTitle()}</li>
+ * </ul>
+ *
+ * <h3><a name="resources"></a>CSS and JavaScript resources</h3>
*
* The Menu control makes use of the following resources
* (which Click automatically deploys to the application directory, <tt>/click</tt>):
@@ -556,9 +628,60 @@ public class Menu extends AbstractContro
}
/**
- * Return the label of the Menu item.
+ * Return the menu item display label.
+ * <p/>
+ * If the label value is null, this method will attempt to find a
+ * localized label message in the parent messages of the root menu using the
+ * key:
+ *
+ * <blockquote>
+ * <tt>getName() + ".label"</tt>
+ * </blockquote>
+ *
+ * If not found then the message will be looked up in the
+ * <tt>/click-control.properties</tt> file using the same key.
+ * If a value is still not found, the Menu name will be converted
+ * into a label using the method: {@link ClickUtils#toLabel(String)}
+ * <p/>
+ * For example given the properties file <tt>src/click-page.properties</tt>:
+ *
+ * <pre class="codeConfig">
+ * <span class="st">customers</span>.label=<span class="red">Customers</span>
+ * <span class="st">customers</span>.title=<span class="red">Find a specific customer</span> </pre>
+ *
+ * The menu.xml (<b>note</b> that no label attribute is present):
+ * <pre class="prettyprint">
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ * <menu>
+ * <menu name="customers" path="customers.htm" roles="view-customers"/>
+ *
+ * ...
+ * </menu> </pre>
+ *
+ * Will render the Menu label and title properties as:
+ *
+ * <pre class="codeHtml">
+ * <li><a title="<span class="red">Find a specific customer</span>" ... ><span class="red">Customers</span></a></li> </pre>
+ *
+ * When a label value is not set, or defined in any properties files, then
+ * its value will be created from the Menu name.
+ * <p/>
+ * For example given the <tt>menu.xml</tt> file:
*
- * @return the label of the Menu item
+ * <pre class="prettyprint">
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ * <menu>
+ * <menu name="product" path="product.htm" roles="view-product"/>
+ *
+ * ...
+ * </menu> </pre>
+ *
+ * Will render the Menu label as:
+ *
+ * <pre class="codeHtml">
+ * <li><a ... ><span class="red">Product</span></a></li> </pre>
+ *
+ * @return the display label of the Menu item
*/
public String getLabel() {
// Return cached label, if set
@@ -806,9 +929,41 @@ public class Menu extends AbstractContro
}
/**
- * Return the title attribute of the Menu item.
+ * Return the 'title' attribute of the Menu item, or null if not defined.
+ * <p/>
+ * If the title value is null, this method will attempt to find a
+ * localized title message in the parent messages of the root menu using the
+ * key:
+ *
+ * <blockquote>
+ * <tt>getName() + ".title"</tt>
+ * </blockquote>
+ *
+ * If not found then the message will be looked up in the
+ * <tt>/click-control.properties</tt> file using the same key. If still
+ * not found the title will be left as null and will not be rendered.
+ * <p/>
+ * For example given the properties file <tt>src/click-page.properties</tt>:
+ *
+ * <pre class="codeConfig">
+ * <span class="st">customers</span>.label=<span class="red">Customers</span>
+ * <span class="st">customers</span>.title=<span class="red">Find a specific customer</span> </pre>
*
- * @return the title attribute of the Menu item
+ * The menu.xml (<b>note</b> that no title attribute is present):
+ * <pre class="prettyprint">
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ * <menu>
+ * <menu name="customers" path="customers.htm" roles="view-customers"/>
+ *
+ * ...
+ * </menu> </pre>
+ *
+ * Will render the Menu label and title properties as:
+ *
+ * <pre class="codeHtml">
+ * <li><a title="<span class="red">Find a specific customer</span>" ... ><span class="red">Customers</span></a></li> </pre>
+ *
+ * @return the 'title' attribute of the Menu item
*/
public String getTitle() {
// Return cached title if set
@@ -1012,16 +1167,17 @@ public class Menu extends AbstractContro
/**
* Render an HTML representation of the Menu.
* <p/>
- * If this menu is the root menu ({@link #isRoot()} returns true), the menu
- * and all its submenus (recursively), will be rendered by delegating
- * rendering to the method
- * {@link #renderRootMenu(org.apache.click.util.HtmlStringBuffer)}. The menu
- * structure will be rendered as an HTML List consisting of <ul> and
- * <li> elements.
+ * If <tt>this</tt> menu instance is the root menu
+ * ({@link #isRoot()} returns true), the menu and all its submenus
+ * (recursively), will be rendered by delegating rendering to the method
+ * {@link #renderRootMenu(org.apache.click.util.HtmlStringBuffer) renderRootMenu}.
+ * The menu structure will be rendered as an HTML List consisting of <ul>
+ * and <li> elements.
* <p/>
- * If this menu is <tt>not</tt> the root menu, this menu will be rendered
- * on its own by delegating rendering to the method
+ * If <tt>this</tt> menu instance is <tt>not</tt> the root menu, this menu
+ * will be rendered by delegating rendering to the method
* {@link #renderMenuLink(org.apache.click.util.HtmlStringBuffer, org.apache.click.extras.control.Menu)}.
+ * The menu will be rendered as a link: <a>.
* <p/>
* By having two render modes one can render the entire menu
* automatically, or render each menu item manually using a Velocity macro.
@@ -1080,6 +1236,13 @@ public class Menu extends AbstractContro
/**
* Render an html represenatation of the menu list (<ul>) structure.
+ * <p/>
+ * <b>Please note</b>: the method
+ * {@link #canRender(org.apache.click.extras.control.Menu, int) canRender(menu)}
+ * controls whether menu items are rendered or not. If <tt>canRender</tt>
+ * returns true, the menu item is rendered, otherwise it is skipped.
+ *
+ * @see #canRender(org.apache.click.extras.control.Menu, int)
*
* @param buffer the buffer to render to
* @param menu the menu that is currently rendered
@@ -1121,12 +1284,13 @@ public class Menu extends AbstractContro
}
/**
- * Return true if the given menu can be rendered, false otherwise. If the
- * menu {@link #hasRoles() has roles} defined, this method will return
- * true if the user is in one of the menu roles, false otherwise.
+ * Return true if the given menu can be rendered, false otherwise.
+ * <p/>
+ * If the menu {@link #hasRoles() has roles} defined, this method will return
+ * true if the user is in one of the menu roles, false otherwise. This method
+ * delegates to {@link #isUserInRoles()} if the menu has roles defined.
* <p/>
- * This method delegates to {@link #isUserInRoles()} if the menu has roles
- * defined.
+ * If the menu has no roles defined, this method returns true.
*
* @param menu the menu that should be rendered or not
* @param depth the current depth in the menu hierarchy
Modified: click/trunk/click/extras/src/org/apache/click/extras/control/MenuFactory.java
URL: http://svn.apache.org/viewvc/click/trunk/click/extras/src/org/apache/click/extras/control/MenuFactory.java?rev=932847&r1=932846&r2=932847&view=diff
==============================================================================
--- click/trunk/click/extras/src/org/apache/click/extras/control/MenuFactory.java (original)
+++ click/trunk/click/extras/src/org/apache/click/extras/control/MenuFactory.java Sun Apr 11 07:39:15 2010
@@ -43,14 +43,35 @@ import org.w3c.dom.NodeList;
/**
* Provides a Menu factory for creating application menus from configuration
- * files. Menu factory provides a variety of <tt>getRootMenu</tt> methods for
- * loading the menu. The default {@link #getRootMenu()} method creates menus
+ * files.
+ * <p/>
+ * Menu factory provides a variety of <tt>getRootMenu()</tt> methods for
+ * loading the menus. The default {@link #getRootMenu()} method creates menus
* from the configuration file <tt>/WEB-INF/menu.xml</tt>, or the classpath
- * resource <tt>/menu.xml</tt> if the WEB-INF menu was not resolved. To load
- * menus from an alternate configuration file use one of the <tt>getRootMenu</tt>
- * methods that accept a configuration file name.
+ * resource <tt>/menu.xml</tt> if <tt>WEB-INF/menu.xml</tt> was not resolved.
+ * <p/>
+ * Below is an example <tt>menu.xml</tt> configuration file:
*
- * <h3>MenuFactory Examples</h3>
+ * <pre class="prettyprint">
+ * <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ * <menu>
+ * <menu label="Home" path="user/home.htm" roles="tomcat, role1"/>
+ * <menu label="User" path="user/home.htm" roles="tomcat, role1">
+ * <menu label="User Page 1" path="user/user-1.htm" roles="tomcat, role1"/>
+ * <menu label="User Page 2" path="user/user-2.htm" roles="tomcat, role1"/>
+ * </menu>
+ * <menu label="Admin" path="admin/admin-1.htm" roles="role1">
+ * <menu label="Admin Page 1" path="admin/admin-1.htm" roles="tomcat, role1"/>
+ * <menu label="Admin Page 2" path="admin/admin-2.htm" roles="tomcat, role1"/>
+ * </menu>
+ * </menu> </pre>
+ *
+ * You can also specify an alternative configuration file name to load your
+ * menus from. Just use one of the <tt>getRootMenu</tt> methods that accept a
+ * configuration file name, for example {@link #getRootMenu(java.lang.String, java.lang.String)
+ * getRootMenu(name, fileName)}.
+ *
+ * <h3><a name="examples"></a>MenuFactory Examples</h3>
*
* Below is an example of a MenuFactory being used to set the rootMenu on a
* border page. Typically a border page will define a page template which
@@ -76,6 +97,7 @@ import org.w3c.dom.NodeList;
*
* } </pre>
*
+ * <h3><a name="stateful-pages"></a>Stateful pages</h3>
* Please note if you use stateful pages that are serialized, you probably
* won't want your application menu being serialized to disk or across a cluster
* with your page as well. In these scenarios please follow the pattern below.
@@ -106,6 +128,20 @@ import org.w3c.dom.NodeList;
*
* } </pre>
*
+ * <h3><a name="caching"></a>Caching</h3>
+ * Loading Menus using {@link #getRootMenu()} will automatically cache the
+ * menus for improved performance (technically the menus are only cached when
+ * Click is in <tt>production</tt> or <tt>profile</tt> mode).
+ * <p/>
+ * If you want to manage Menu caching yourself, use one of the
+ * {@link #getRootMenu(boolean) getRootMenu} methods that accepts a boolean
+ * controlling whether or not the menus are cached.
+ * <p/>
+ * A common use case for caching menus yourself is when you need to customize
+ * the menus based on the logged in user. For this scenario you would load the
+ * Menus using {@link #getRootMenu(boolean) getRootMenu(false)}, customize the
+ * menus according to the user profile, and cache the menus in the HttpSession.
+ *
* @see Menu
*/
public class MenuFactory implements Serializable {
@@ -167,7 +203,7 @@ public class MenuFactory implements Seri
/**
* Return root menu item defined in the WEB-INF/menu.xml or classpath
- * menu.xml, creating menu items using the provided Menu class and the JEE
+ * menu.xml, creating menu items using the provided menu class and the JEE
* RoleAccessController.
*
* @param menuClass the menu class to create new Menu instances from
@@ -209,9 +245,9 @@ public class MenuFactory implements Seri
}
/**
- * Return root menu item defined by the given fileName under WEB-INF or the
- * classpath, creating menu items using the Menu class and the JEE
- * RoleAccessController.
+ * Return root menu item defined by the given name and fileName under
+ * WEB-INF or the classpath, creating menu items using the Menu class and
+ * the JEE RoleAccessController.
*
* @param name the name of the root menu
* @param fileName the fileName defining the menu definitions
@@ -224,9 +260,21 @@ public class MenuFactory implements Seri
}
/**
- * Return root menu item defined by the given fileName under WEB-INF or the
- * classpath, creating menu items using the Menu class and the JEE
- * RoleAccessController.
+ * Return root menu item defined by the given name and fileName under WEB-INF
+ * or the classpath, creating menu items using the provided menu class and
+ * AccessController.
+ * <p/>
+ * Example usage:
+ * <pre class="prettyprint">
+ * public void onInit() {
+ * MenuFactory factory = new MenuFactory();
+ * String menuName = "mymenu";
+ * String fileName = "mymenu.xml";
+ * AccessController accessController = new RoleAccessController();
+ * boolean cached = true;
+ *
+ * factory.getRootMenu(menuName, fileName, accessController, cached, MyMenu.class);
+ * } </pre>
*
* @param name the name of the root menu
* @param fileName the fileName defining the menu definitions
@@ -258,9 +306,12 @@ public class MenuFactory implements Seri
ServletContext servletContext = Context.getThreadLocalContext().getServletContext();
ConfigService configService = ClickUtils.getConfigService(servletContext);
- if (configService.isProductionMode() || configService.isProfileMode()) {
- // Cache menu in production modes
- cacheRootMenu(rootMenu);
+ if (cached) {
+
+ if (configService.isProductionMode() || configService.isProfileMode()) {
+ // Cache menu in production modes
+ cacheRootMenu(rootMenu);
+ }
}
return rootMenu;