6 Replies Latest reply on Aug 2, 2007 2:32 AM by jbuechel

    Component configuration with complex types

    jbuechel

      I'm trying to configure a component (which should provide a menu structure to the view) with complex types via components.xml file.

      So would it be possible to configure the hole menu stucture in the components.xml file?

      Code such following should be replaced:


      @Out
      List htmlDropDownMenuList;

      @Factory("htmlDropDownMenuList")
      public void buildMenu() {
      log.info("buildMenu called");

      htmlDropDownMenuList = new ArrayList<HtmlDropDownMenu>();

      /*************** Menu 1 ***************/
      HtmlDropDownMenu htmlDropDownMenu = new HtmlDropDownMenu();
      htmlDropDownMenu.setValue(messages.get("dropDownMenu1"));

      /**** MenuItem 1 ****/
      HtmlMenuItem htmlMenuItem = new HtmlMenuItem();
      htmlMenuItem.setValue(messages.get("dropDownMenu1.menuItem1"));
      htmlMenuItem.setActionExpression(
      Expressions.instance().createMethodExpression("modules/queryCatalog/queryCatalog.xhtml").toUnifiedMethodExpression());

      htmlDropDownMenu.getChildren().add(htmlMenuItem);

      htmlDropDownMenuList.add(htmlDropDownMenu);


      I couldn't find something similar in the reference or this forum.
      Any ideas would be very appreciated.

        • 1. Re: Component configuration with complex types
          atao

          Hello,

          I just started to work on a menu build through configuration file, but:
          - without using any of the "standard" configuration files as "components.xml": I define a specific "menus.xml" file in the same way that pages.xml
          - and agnostic about implementation, even if by default it'll be RichFaces.

          Atm a lot of things are still missing but it works. If you are interested...

          • 2. Re: Component configuration with complex types
            jbuechel

            Hi

            Yes i am. If you could provide some sample code would be great!

            • 3. Re: Component configuration with complex types
              jbuechel

              I'm wondering how others are configuring their menus..

              Or is there a completely different approach? Just a hint? ;-)

              • 4. Re: Component configuration with complex types
                pmuir

                You could do this via components.xml but it would be quite verbose due to not being able to nest components. If this is a static menu, then I would ui:include a facelet.

                • 5. Re: Component configuration with complex types
                  atao

                  It's really a work in progress.

                  I just checked it againt Seam 2 cvs.

                  So, the code as it is...

                  All the calls go through MenuManager

                  package org.jboss.seam.menu;
                  
                  import static org.jboss.seam.ScopeType.APPLICATION;
                  import static org.jboss.seam.annotations.Install.BUILT_IN;
                  
                  import java.io.InputStream;
                  import java.util.Collections;
                  import java.util.HashMap;
                  import java.util.List;
                  import java.util.Map;
                  
                  import org.dom4j.DocumentException;
                  import org.dom4j.Element;
                  import org.jboss.seam.Component;
                  import org.jboss.seam.annotations.Create;
                  import org.jboss.seam.annotations.Install;
                  import org.jboss.seam.annotations.Name;
                  import org.jboss.seam.annotations.Scope;
                  import org.jboss.seam.annotations.intercept.BypassInterceptors;
                  import org.jboss.seam.contexts.Contexts;
                  import org.jboss.seam.log.LogProvider;
                  import org.jboss.seam.log.Logging;
                  import org.jboss.seam.menu.MenuItem.ItemType;
                  import org.jboss.seam.menu.NavigationFactory.NavigationType;
                  import org.jboss.seam.util.Resources;
                  import org.jboss.seam.util.XML;
                  
                  /**
                   * Provide menu items
                   *
                   * - in the same application, it should be possible to use different implementations through component configuration
                   * atm the only one available is RichFaces
                   * - in menus.xml, everything is a item, without no information about how to show these items
                   * - the way that a menu is inserted in a page is fixed on from the page side with the choice between 3 methods:
                   * - getNavigationItem : return an simple item
                   * - getNavigationMenu : return a single top menu
                   * - getNavigationMenus: retourne a list of top menus
                   * What is exactly returned depends of the implementation.
                   * - any item, whatever its declaration place is, can be named with "id" attribute and so reused
                   * (in a tag, through attribut "refid")
                   * - TODO to set parameters specifics for a given implementation, with the tag
                   * <specific type="richfaces">...</specific>
                   * inside any item.
                   * - all seam parameters defined for a link are directly available; atm only propagation
                   * - the children of an item can be "unwrapped" i.e. used in place of the item.
                   *
                   * Syntaxe of a menu file:
                   * <menus>
                   * <item id="...">
                   * <item id="..."
                   * label="..."
                   * icon="..."
                   * description
                   * rendered
                   * disabled
                   * action
                   * type
                   * propagation
                   * split
                   * target
                   * >
                   * ...
                   * </item>
                   * <item>
                   * ...
                   * </item>
                   * ...
                   * </menus>
                   *
                   * @author Pierre
                   *
                   */
                  @Scope(APPLICATION)
                  @BypassInterceptors
                  @Name("menumanager")
                  @Install(precedence = BUILT_IN)
                  public class MenuManager {
                   private static String EMPTY_STRING = "";
                   private static String TRUE_STRING = "true";
                   private static String ITEM_TAG = "item";
                   private static String ID_ATTR = "id";
                   private static String REFID_ATTR = "refid";
                   private static String ICON_ATTR = "icon";
                   private static String LABEL_ATTR = "label";
                   private static String HOTKEY_ATTR = "accesskey";
                   private static String DESCRIPTION_ATTR = "description";
                   private static String RENDERED_ATTR = "rendered";
                   private static String DISABLED_ATTR = "disabled";
                   private static String ACTION_ATTR = "action";
                   private static String TYPE_ATTR = "type";
                   private static String PROPAGATION_ATTR = "propagation";
                   private static String TARGET_ATTR = "target";
                   private static String UNWRAP_ATTR = "unwrap";
                  
                   public static NavigationType MENU_LIST_TYPE = NavigationType.GROUP;
                   public static NavigationType MENU_TYPE = NavigationType.ROOT;
                  
                   private String menusFile = "/WEB-INF/menus.xml";
                   private String menuImpl = "Richfaces";
                  
                   private static final LogProvider log = Logging
                   .getLogProvider(MenuManager.class);
                   private Map<String, MenuItem> menusById = Collections
                   .synchronizedMap(new HashMap<String, MenuItem>());
                   private NavigationFactory factory;
                  
                   @Create
                   public void initialize() {
                   InputStream stream = Resources.getResourceAsStream(menusFile, null);
                   if (stream == null) {
                   log.debug("no " + menusFile + " file found");
                   }
                   if (stream != null) {
                   log.debug("reading " + menusFile);
                   parse(stream);
                   }
                  
                   factory = NavigationFactory.getInstance(menuImpl);
                   }
                  
                   public static MenuManager instance() {
                   if (Contexts.isApplicationContextActive()) {
                   return (MenuManager) Component.getInstance(MenuManager.class,
                   APPLICATION);
                   } else // tests
                   {
                   return new MenuManager();
                   }
                   }
                  
                   /**
                   *Get a MenuItem from cache
                   */
                   public MenuItem getMenu(String id) {
                   MenuItem item = menusById.get(id);
                   if (null == item)
                   return null;
                  
                   if ((item.getRefid() != null) && !EMPTY_STRING.equals(item.getRefid())) {
                   item = menusById.get(item.getRefid());
                   }
                   return item;
                   }
                  
                   /**
                   * Get a Menu List to insert in a menu bar
                   */
                   public Object getNavigationMenus(String id) {
                   return factory
                   .getNavigationItem(menusById, getMenu(id), MENU_LIST_TYPE);
                   }
                  
                   /**
                   * Get a Menu to insert in a menu bar
                   */
                   public Object getNavigationMenu(String id) {
                   return factory.getNavigationItem(menusById, getMenu(id), MENU_TYPE);
                   }
                  
                   /**
                   * Get a menu item
                   */
                   public Object getNavigationItem(String id) {
                   return factory.getNavigationItem(menusById, getMenu(id));
                   }
                  
                   /**
                   * Parse a menus.xml file
                   */
                   private void parse(InputStream stream) {
                   Element root = getDocumentRoot(stream);
                  
                   List<Element> elements = root.elements(ITEM_TAG);
                   for (Element item : elements) {
                   String itemId = item.attributeValue(ID_ATTR);
                   if (null == itemId || EMPTY_STRING.equals(itemId)) {
                   // TODO: use an other type of exception?
                   throw new IllegalStateException("Must specify item-id for '"
                   + item.attributeValue(LABEL_ATTR) + "' tag.");
                   }
                   parseItem(item);
                   }
                   }
                  
                   private String parseLabel(Element element) {
                   return element.attributeValue(LABEL_ATTR);
                   }
                  
                   private ItemType parseItemType(Element element) {
                   String type = element.attributeValue(TYPE_ATTR);
                   if (null == type) return ItemType.DEFAULT;
                   try
                   {
                   return ItemType
                   .valueOf(type.toUpperCase());
                   }
                   catch (IllegalArgumentException e)
                   {
                   return ItemType.DEFAULT;
                   }
                   }
                  
                   private MenuItem parseItem(Element element) {
                  
                   String itemId = element.attributeValue(ID_ATTR);
                   MenuItem item = null;
                   String refid = element.attributeValue(REFID_ATTR);
                   if (null != refid && !EMPTY_STRING.equals(refid)) {
                   item = new MenuItem(refid);
                   item.setUnwrap(Boolean.parseBoolean(element
                   .attributeValue(UNWRAP_ATTR)));
                   } else {
                   item = new MenuItem(itemId, element.attributeValue(ICON_ATTR),
                   parseLabel(element), element.attributeValue(HOTKEY_ATTR),
                   element.attributeValue(DESCRIPTION_ATTR), Boolean
                   .parseBoolean(element.attributeValue(RENDERED_ATTR,
                   TRUE_STRING)), Boolean.parseBoolean(element
                   .attributeValue(DISABLED_ATTR)), element
                   .attributeValue(ACTION_ATTR),
                   parseItemType(element), element
                   .attributeValue(PROPAGATION_ATTR), element
                   .attributeValue(TARGET_ATTR));
                   item.setText(element.getText());
                  
                   for (Element child : (List<Element>) element.elements(ITEM_TAG)) {
                   item.getItems().add(parseItem(child));
                   }
                   }
                  
                   if (null != itemId && !EMPTY_STRING.equals(itemId)) {
                   menusById.put(itemId, item);
                   }
                  
                   return item;
                   }
                  
                   /**
                   * Get the root element of the document
                   */
                   private static Element getDocumentRoot(InputStream stream) {
                   try {
                   return XML.getRootElement(stream);
                   } catch (DocumentException de) {
                   throw new RuntimeException(de);
                   }
                   }
                  
                   /**
                   * @return the menuImpl
                   */
                   public String getMenuImpl() {
                   return this.menuImpl;
                   }
                  
                   /**
                   * @param menuImpl the menuImpl to set
                   */
                   public void setMenuImpl(String menuImpl) {
                   this.menuImpl = menuImpl;
                   }
                  
                   /**
                   * @return the menusFile
                   */
                   public String getMenusFile() {
                   return this.menusFile;
                   }
                  
                   /**
                   * @param menusFile the menusFile to set
                   */
                   public void setMenusFile(String menusFile) {
                   this.menusFile = menusFile;
                   }
                  
                   public Map<String, MenuItem> getMenus() {
                   return menusById;
                   }
                  }
                  
                  


                  with tree classes to do the job
                  - an abstract one: NavigationFactory
                  - Richfaces implementation: RichFacesNavigationFactory
                  - and a value object: MenuItem

                  package org.jboss.seam.menu;
                  
                  import java.util.Map;
                  
                  import org.jboss.seam.core.Expressions;
                  import org.jboss.seam.log.LogProvider;
                  import org.jboss.seam.log.Logging;
                  
                  public abstract class NavigationFactory {
                  
                   public static enum NavigationType {
                   ROOT, GROUP, INSIDE
                   }
                   protected static final String EMPTY_STRING = "";
                   private static final String PATH_SEP = ".";
                  
                   protected Map<String, MenuItem> refmap;
                  
                   private static final String CLASS_SUFFIX = NavigationFactory.class
                   .getSimpleName();
                  
                   protected static final LogProvider log = Logging
                   .getLogProvider(NavigationFactory.class);
                  
                   protected NavigationFactory() {
                   }
                  
                   /**
                   *
                   * @param impl either a simple prefix if the implementation is in the same package
                   * or a full package name for a NavigationFactory class in an other package
                   * @return
                   */
                   public static NavigationFactory getInstance(String impl) {
                   NavigationFactory factory = null;
                   String className = impl;
                   try {
                   if (impl.indexOf(PATH_SEP) < 0) {
                   className = NavigationFactory.class.getPackage().getName()
                   + PATH_SEP + className;
                   if (!impl.endsWith(CLASS_SUFFIX)) {
                   className += CLASS_SUFFIX;
                   }
                   }
                   Class clazz = Class.forName(className);
                   factory = (NavigationFactory) clazz.newInstance();
                   } catch (ClassNotFoundException e) {
                   log.error("Navigation factory not found for '" + className + "'.",
                   e);
                   } catch (IllegalAccessException e) {
                   log.error("Navigation factory not accessible for '" + className
                   + "'.", e);
                   } catch (InstantiationException e) {
                   log.error("Navigation factory can't be instantiated for '"
                   + className + "'.", e);
                   }
                  
                   return factory;
                   }
                  
                   /**
                   * gives a standard navigation item
                   *
                   * @param itemId
                   * @return
                   */
                   public Object getNavigationItem(Map<String, MenuItem> refmap, MenuItem item) {
                   return getNavigationItem(refmap, item, NavigationType.INSIDE);
                   }
                  
                   /**
                   * gives a navigation item, either a standard one with NavigationType.INSIDE or a menu bar's one
                   * with NavigationType.ROOT or NavigationType.GROUP
                   *
                   * @param itemId
                   * @param type
                   * @return
                   */
                   public Object getNavigationItem(Map<String, MenuItem> refmap,
                   MenuItem item, NavigationType type) {
                   this.refmap = refmap;
                   return getNavigationItem(item, type);
                   }
                  
                   protected abstract Object getNavigationItem(MenuItem item,
                   NavigationType type);
                  
                   protected MenuItem getRefItem(MenuItem item) {
                   if ((null == item) || (null == item.getRefid())
                   || EMPTY_STRING.equals(item.getRefid())) {
                   return item;
                   }
                   return getRefItem(refmap.get(item.getRefid()));
                   }
                  
                   protected Object parseLabel(String expression) {
                   return null == expression ? null : Expressions.instance()
                   .createValueExpression(expression).getValue();
                   }
                  
                   protected Object parseAction(String expression) {
                   return null == expression ? null : Expressions.instance()
                   .createValueExpression(expression).getValue();
                   }
                  
                  }
                  


                  package org.jboss.seam.menu;
                  
                  import javax.el.ELContext;
                  import javax.el.ExpressionFactory;
                  import javax.el.MethodExpression;
                  import javax.faces.component.UIComponent;
                  import javax.faces.context.FacesContext;
                  
                  import org.jboss.seam.el.SeamExpressionFactory;
                  import org.jboss.seam.ui.component.html.HtmlLink;
                  import org.richfaces.component.html.HtmlDropDownMenu;
                  import org.richfaces.component.html.HtmlMenuGroup;
                  import org.richfaces.component.html.HtmlMenuItem;
                  import org.richfaces.component.html.HtmlMenuSeparator;
                  import org.richfaces.component.html.HtmlToolBarGroup;
                  
                  public class RichfacesNavigationFactory extends NavigationFactory {
                  
                   protected UIComponent getNavigationItem(MenuItem item, NavigationType type) {
                  
                   item = getRefItem(item);
                   if (null == item) {
                   item = new MenuItem(null);
                   }
                  
                   if (NavigationType.ROOT == type) {
                   return getDropDownMenu(item);
                   } else if (NavigationType.GROUP == type) {
                   return getToolBarGroup(item);
                   } else if (item.getItems().isEmpty()) {
                   if ((null == item.getLabel())
                   || EMPTY_STRING.equals(item.getLabel())) {
                   return getMenuSeparator(item);
                   } else {
                   return getMenuItem(item);
                   }
                   } else {
                   return getMenuGroup(item);
                   }
                   }
                  
                   private HtmlToolBarGroup getToolBarGroup(MenuItem item) {
                   HtmlToolBarGroup group = new HtmlToolBarGroup();
                   group.setId(item.getId());
                   group.setRendered(item.isRendered());
                   copyChildren(item, group, NavigationType.ROOT);
                   return group;
                   }
                  
                   private HtmlDropDownMenu getDropDownMenu(MenuItem item) {
                   HtmlDropDownMenu menu = new HtmlDropDownMenu();
                   menu.setId(item.getId());
                   menu.setValue(parseLabel(item.getLabel()));
                   menu.setRendered(item.isRendered());
                   copyChildren(item, menu, NavigationType.INSIDE);
                   return menu;
                   }
                  
                   private HtmlMenuItem getMenuItem(MenuItem item) {
                   HtmlMenuItem navItem = new HtmlMenuItem();
                   navItem.setId(item.getId());
                   navItem.setIcon(item.getIcon());
                   navItem.setRendered(item.isRendered());
                   boolean linked = false;
                   if (null == item.getPropagation()) {
                   if (MenuItem.ItemType.DIRECT.equals(item.getType())) // i.e. a link with its protocole, e.g. "http://..."
                   {
                   navItem.setOnclick("document.location.href='"
                   + parseAction(item.getAction()) + "'");
                   navItem.setSubmitMode("none");
                   linked = true;
                   } else if (MenuItem.ItemType.BINDING.equals(item.getType())) {
                   ExpressionFactory factory = SeamExpressionFactory.INSTANCE;
                   ELContext context = FacesContext.getCurrentInstance()
                   .getELContext();
                   MethodExpression expression = factory.createMethodExpression(
                   context, item.getAction(), Object.class,
                   new Class<?>[0]);
                   navItem.setActionExpression(expression);
                   linked = true;
                   }
                   if (linked) {
                   navItem.setDisabled(item.isDisabled());
                   navItem.setValue(parseLabel(item.getLabel()));
                   }
                   }
                   if (!linked) // by default, jsf view id; used also if propagation is specified
                   {
                   HtmlLink link = new HtmlLink();
                   link.setValue(parseLabel(item.getLabel()));
                   link.setView((String) parseAction(item.getAction()));
                   link.setPropagation(item.getPropagation());
                   link.setDisabled(item.isDisabled());
                   navItem.getChildren().add(link);
                   navItem.setSubmitMode("none");
                   navItem.setStyleClass("withlink");
                   }
                  
                   return navItem;
                   }
                  
                   private HtmlMenuGroup getMenuGroup(MenuItem item) {
                   HtmlMenuGroup group = new HtmlMenuGroup();
                   group.setId(item.getId());
                   group.setIcon(item.getIcon());
                   group.setValue(parseLabel(item.getLabel()));
                   group.setDisabled(item.isDisabled());
                   group.setRendered(item.isRendered());
                   copyChildren(item, group, NavigationType.INSIDE);
                   return group;
                   }
                  
                   private HtmlMenuSeparator getMenuSeparator(MenuItem item) {
                   return new HtmlMenuSeparator();
                   }
                  
                   private void copyChildren(MenuItem item, UIComponent group,
                   NavigationType type) {
                   for (MenuItem child : item.getItems()) {
                   if (null != child && child.isUnwrap()) {
                   child = getRefItem(child);
                   for (MenuItem subchild : child.getItems()) {
                   group.getChildren().add(getNavigationItem(subchild, type));
                   }
                   } else {
                   group.getChildren().add(getNavigationItem(child, type));
                   }
                   }
                   }
                  
                  }
                  


                  package org.jboss.seam.menu;
                  
                  import java.util.ArrayList;
                  import java.util.HashMap;
                  import java.util.List;
                  import java.util.Map;
                  
                  /**
                   * Nota: attribute "type" gives the type of action, with value "direct", "binding" or "default"
                   * The default value is associated with jsf link.
                   *
                   * Nota: to deal with implementation specific needs, use "specific" tag in the body of the item.
                   * The implementation is specified by the attribute "type" of this tag. This specific data are stored
                   * in data property.
                   *
                   * @author Pierre
                   *
                   */
                  public class MenuItem {
                   public static enum ItemType {
                   DIRECT, BINDING, DEFAULT
                   }
                  
                   private String id;
                   private String refid;
                   private boolean unwrap;
                   private String text;
                   private String icon;
                   private String label;
                   private String hotkey;
                   private String description;
                   private boolean rendered;
                   private boolean disabled;
                   private String action;
                   private ItemType type;
                   private String propagation;
                   private String target;
                   private Map<String, Object> data;
                   private List<MenuItem> items = new ArrayList<MenuItem>();
                  
                   public MenuItem(String refid) {
                   this.refid = refid;
                   }
                  
                   public MenuItem(String id, String icon, String label, String hotkey,
                   String description, boolean rendered, boolean disabled,
                   String action, ItemType type, String propagation, String target) {
                   this.id = id;
                   this.icon = icon;
                   this.label = label;
                   this.description = description;
                   this.rendered = rendered;
                   this.disabled = disabled;
                   this.action = action;
                   this.type = type;
                   this.propagation = propagation;
                   this.hotkey = hotkey;
                   this.target = target;
                   }
                  
                   /**
                   * @return the items
                   */
                   public List<MenuItem> getItems() {
                   return this.items;
                   }
                  
                   /**
                   * @param items the items to set
                   */
                   public void setItems(List<MenuItem> items) {
                   this.items = items;
                   }
                  
                   /**
                   * @return the action
                   */
                   public String getAction() {
                   return this.action;
                   }
                  
                   /**
                   * @param action the action to set
                   */
                   public void setAction(String action) {
                   this.action = action;
                   }
                  
                   /**
                   * @return the action type
                   */
                   public ItemType getType() {
                   return this.type;
                   }
                  
                   /**
                   * @param type the type to set
                   */
                   public void setType(ItemType type) {
                   this.type = type;
                   }
                  
                   /**
                   * @return the propagation
                   */
                   public String getPropagation() {
                   return this.propagation;
                   }
                  
                   /**
                   * @param propagation the propagation to set
                   */
                   public void setPropagation(String propagation) {
                   this.propagation = propagation;
                   }
                  
                   /**
                   * @return the description
                   */
                   public String getDescription() {
                   return this.description;
                   }
                  
                   /**
                   * @param description the description to set
                   */
                   public void setDescription(String description) {
                   this.description = description;
                   }
                  
                   /**
                   * @return the disabled
                   */
                   public boolean isDisabled() {
                   return this.disabled;
                   }
                  
                   /**
                   * @param disabled the disabled to set
                   */
                   public void setDisabled(boolean disabled) {
                   this.disabled = disabled;
                   }
                  
                   /**
                   * @return the icon
                   */
                   public String getIcon() {
                   return this.icon;
                   }
                  
                   /**
                   * @param icon the icon to set
                   */
                   public void setIcon(String icon) {
                   this.icon = icon;
                   }
                  
                   /**
                   * @return the id
                   */
                   public String getId() {
                   return this.id;
                   }
                  
                   /**
                   * @param id the id to set
                   */
                   public void setId(String id) {
                   this.id = id;
                   }
                  
                   /**
                   * @return the label
                   */
                   public String getLabel() {
                   return this.label;
                   }
                  
                   /**
                   * @param label the label to set
                   */
                   public void setLabel(String label) {
                   this.label = label;
                   }
                  
                   /**
                   * @return the rendered
                   */
                   public boolean isRendered() {
                   return this.rendered;
                   }
                  
                   /**
                   * @param rendered the rendered to set
                   */
                   public void setRendered(boolean rendered) {
                   this.rendered = rendered;
                   }
                  
                   /**
                   * @return the target
                   */
                   public String getTarget() {
                   return this.target;
                   }
                  
                   /**
                   * @param target the target to set
                   */
                   public void setTarget(String target) {
                   this.target = target;
                   }
                  
                   /**
                   * @return the hotkey
                   */
                   public String getHotkey() {
                   return this.hotkey;
                   }
                  
                   /**
                   * @param hotkey the hotkey to set
                   */
                   public void setHotkey(String hotkey) {
                   this.hotkey = hotkey;
                   }
                  
                   /**
                   * @return the data
                   */
                   public Map<String, Object> getData() {
                   return this.data;
                   }
                  
                   /**
                   * @param data the data to set
                   */
                   public void setData(Map<String, Object> data) {
                   this.data = data;
                   }
                   public void addData(String impl, Object data) {
                   if (null == this.data) {
                   this.data = new HashMap<String, Object>();
                   }
                   this.data.put(impl, data);
                   }
                  
                   /**
                   * @return the refid
                   */
                   public String getRefid() {
                   return this.refid;
                   }
                  
                   /**
                   * @param refid the refid to set
                   */
                   public void setRefid(String refid) {
                   this.refid = refid;
                   }
                  
                   /**
                   * The text from the item body
                   *
                   * @return the text
                   */
                   public String getText() {
                   return this.text;
                   }
                  
                   /**
                   * @param text the text to set
                   */
                   public void setText(String text) {
                   this.text = text;
                   }
                  
                   /**
                   * @return the unwrap
                   */
                   public boolean isUnwrap() {
                   return this.unwrap;
                   }
                  
                   /**
                   * @param unwrap the unwrap to set
                   */
                   public void setUnwrap(boolean unwrap) {
                   this.unwrap = unwrap;
                   }
                  
                   public String toString() {
                   return this.getClass().getSimpleName() + ", id = " + id
                   + (refid == null ? ", " : " (" + refid + "), ") + "label = '"
                   + label + "', action = " + action;
                   }
                  }
                  



                  Then to use it:
                  - create a menus.xml, e.g.:
                  <menus>
                  
                   <item id="HomeMenu" >
                   <item refid="EntityMenu" />
                   <item refid="MainMenu" unwrap="true" />
                   </item>
                  
                   <item id="EntityMenu" label="#{messages['view.menu.label.entities']}" >
                   <item label="#{messages['view.menu.list.person']}" action="/PersonList.xhtml" propagation="none" />
                   <item label="#{messages['view.menu.list.branch']}" action="/BranchList.xhtml" propagation="none" />
                   <item label="#{messages['view.menu.list.fund']}" action="/FundList.xhtml" propagation="none" />
                   <item label="#{messages['view.menu.list.payslip']}" action="/PayslipList.xhtml" propagation="none" />
                   <item label="#{messages['view.menu.list.worker']}" action="/WorkerList.xhtml" propagation="none" />
                   <item label="#{messages['view.menu.list.contract']}" action="/ContractList.xhtml" propagation="none" />
                   <item label="#{messages['view.menu.list.address']}" action="/AddressList.xhtml" propagation="none" />
                   <item label="#{messages['view.menu.list.rubric']}" action="/RubricList.xhtml" propagation="none" />
                   <item label="#{messages['view.menu.list.profil']}" action="/ProfilList.xhtml" propagation="none" />
                   <item label="#{messages['view.menu.list.job']}" action="/JobList.xhtml" propagation="none" />
                   <item label="#{messages['view.menu.list.payItem']}" action="/PayItemList.xhtml" propagation="none" />
                   </item>
                  
                   <item id="MainMenu" >
                   <item refid="FileMenu" />
                   <item refid="EmployeeMenu" />
                   <item refid="PayslipMenu" />
                   <item refid="ReportMenu" />
                   <item refid="ToolMenu" />
                   <item refid="HelpMenu" />
                   </item>
                  
                   <item id="FileMenu" label="#{messages['menu.company']}">
                   <item label="#{messages['menu.quit']}" action="#{messages['view.menu.link.site.company']}" type="direct" />
                   </item>
                  
                   <item id="EmployeeMenu" label="#{messages['menu.employee']}">
                   <item label="#{messages['menu.employee.list']}" action="/WorkerList.xhtml" propagation="none" />
                   <item />
                   <item label="#{messages['menu.employee.contract.list']}" action="/ContractList.xhtml" propagation="none" />
                   </item>
                  
                   <item id="PayslipMenu" label="#{messages['menu.payslip']}">
                   <item label="#{messages['menu.payslip.list']}" action="/PayslipList.xhtml" propagation="none" />
                   </item>
                  
                   <item id="ReportMenu" label="#{messages['menu.report']}">
                   </item>
                  
                   <item id="ToolMenu" label="#{messages['menu.tool']}">
                   </item>
                  
                   <item id="HelpMenu" label="#{messages['menu.help']}">
                   <item label="#{messages['view.menu.label.site.jboss']}" action="#{messages['view.menu.link.site.jboss']}" type="direct" />
                   <item label="#{messages['view.menu.label.help']}" action="/Help.xhtml" target="_blank"/>
                   </item>
                  
                   <item id="PersonListMenu" >
                   <item label="#{messages['entity.person.name']}">
                   <item label="#{messages['view.global.button.add']}"
                   action="/PersonEdit.xhtml" />
                   </item>
                   </item>
                  
                   <item id="ContractListMenu" >
                   <item label="#{messages['entity.contract.name']}">
                   <item label="#{messages['view.global.button.add']}"
                   action="/WorkerList.xhtml" />
                   </item>
                   </item>
                  
                   <item id="ContractViewMenu" >
                   <item label="#{messages['entity.contract.name']}">
                   <item label="#{messages['menu.link.contract.create.payslips']}"
                   action="#{customContractHome.createPayslip}"
                   type="binding"/>
                   </item>
                   </item>
                  
                  </menus>
                  


                  - and use it with a menu layout:
                  <rich:toolBar
                   xmlns="http://www.w3.org/1999/xhtml"
                   xmlns:ui="http://java.sun.com/jsf/facelets"
                   xmlns:h="http://java.sun.com/jsf/html"
                   xmlns:f="http://java.sun.com/jsf/core"
                   xmlns:s="http://jboss.com/products/seam/taglib"
                   xmlns:rich="http://richfaces.ajax4jsf.org/rich">
                  <h:form id="menuBar">
                  
                  <style type="text/css">
                   .withlink a {display:inline-block; width: 100%;}
                   html>/**/body .withlink a {display: block; width: 100%;}
                   html>/**/body .withlink span{float: left;}
                   html>/**/body .withlink span + span {float: none; display: block;}
                  </style>
                  
                  <style type="text/css">
                   .withHighIndex div {z-index: 100;}
                  </style>
                  
                   <rich:toolBarGroup>
                   <h:outputFormat value="#{messages['view.menu.title.project']}">
                   <f:param value="#{projectName}" />
                   </h:outputFormat>
                   </rich:toolBarGroup>
                  
                  <ui:insert name="menu" />
                  <f:subview rendered="#{empty menuref}">
                  
                   <rich:toolBarGroup>
                   <s:link view="/home.xhtml"
                   value="#{messages['view.menu.link.home']}"/>
                   </rich:toolBarGroup>
                  
                   <rich:toolBarGroup styleClass="withHighIndex">
                   <rich:dropDownMenu value="#{messages['view.menu.label.entities']}">
                   <rich:menuItem
                   styleClass="withlink"
                   submitMode="none">
                   <s:link value="#{messages['view.menu.list.profil']}"
                   view="/ProfilList.xhtml" propagation="none" />
                   </rich:menuItem>
                  [...]
                   <rich:menuItem
                   styleClass="withlink"
                   submitMode="none">
                   <s:link value="#{messages['view.menu.list.person']}"
                   view="/PersonList.xhtml" propagation="none" />
                   </rich:menuItem>
                   </rich:dropDownMenu>
                  
                   <rich:dropDownMenu value="#{messages['view.menu.help']}">
                   <rich:menuItem value="#{messages['view.menu.label.site.jboss']}"
                   onclick="document.location.href='#{messages['view.menu.link.site.jboss']}'" submitMode="none" />
                   </rich:dropDownMenu>
                   </rich:toolBarGroup>
                  
                  </f:subview>
                  
                   <rich:toolBarGroup location="right">
                   <h:outputFormat value="#{messages['org.jboss.seam.loginSuccessful']}"
                   rendered="#{identity.loggedIn}">
                   <f:param value="#{identity.username}"/>
                   </h:outputFormat>
                   <s:link view="/login.xhtml"
                   value="#{messages['view.login.button.login']}"
                   rendered="#{not identity.loggedIn}"/>
                   <s:link view="/home.xhtml"
                   action="#{identity.logout}"
                   value="#{messages['view.login.button.logout']}"
                   rendered="#{identity.loggedIn}"/>
                   </rich:toolBarGroup>
                  </h:form>
                  </rich:toolBar>
                  


                  and some view:
                  <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                  
                  <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                   xmlns:s="http://jboss.com/products/seam/taglib"
                   xmlns:ui="http://java.sun.com/jsf/facelets"
                   xmlns:f="http://java.sun.com/jsf/core"
                   xmlns:h="http://java.sun.com/jsf/html"
                   xmlns:rich="http://richfaces.ajax4jsf.org/rich"
                   xmlns:j="http://ext.joda.org/jsf/components"
                   template="layout/template.xhtml">
                  
                  <ui:param name="menuref" value="#{menumanager.getMenu('FundViewMenu')}" />
                  <ui:define name="menu">
                   <rich:toolBarGroup styleClass="withHighIndex" binding="#{menumanager.getNavigationMenus('FundViewMenu')}" />
                  </ui:define>
                  
                  <ui:define name="body">
                  
                   <h:messages globalOnly="true" styleClass="message" id="globalMessages"/>
                  
                   <rich:panel>
                   <f:facet name="header">
                   <h:outputFormat value="#{messages['view.edit.title.show.entity']}">
                   <f:param value="#{messages['entity.fund.name']}"/>
                   </h:outputFormat>
                   </f:facet>
                  
                   <s:decorate id="id" template="layout/display.xhtml">
                   <ui:define name="label">
                   <h:outputText value="#{messages['entity.fund.id.label']}"/>
                   </ui:define>
                   #{fundHome.instance.id}
                   </s:decorate>
                  
                  [...]
                  
                  </ui:define>
                  
                  </ui:composition>
                  




                  • 6. Re: Component configuration with complex types
                    jbuechel

                    Wow! Thanks a lot for your effort. I'll give it a try.

                    jonas