/**
   * Recursively scan through menus to find the MenuAction with menuId.
   *
   * @param menuId, the menu id to search for.
   * @param parentMenu, the parent to start searching from.
   */
  public MenuAction findMenu(Object menuId, MenuAction parentMenu) {
    // if no parent, search from root
    if (parentMenu == null) parentMenu = _rootMenu;

    // delegate
    return (parentMenu == null) ? null : parentMenu.findMenu(menuId);
  }
  /**
   * @return the currently selected menu. If there is no valid current selection then the main menu
   *     is returned.
   */
  public MenuAction getCurrentMenu() {
    assert _user != null;

    if (_currentMenu == null) {
      if (_rootMenu == null) {
        // no mainmenu yet, construct the main menu object and then load
        // base menu items for group (s)
        _rootMenu = new Submenu("Main Menu", "Main Menu", null, null);

        try {
          // find the groups the user is a member of
          boolean isFirst = true;
          Vector gmems = _user.getGroupMemberships();
          for (int i = 0; gmems != null && i < gmems.size(); i++) {
            GroupMembership gm = (GroupMembership) gmems.elementAt(i);
            if (gm != null) {
              // add a spaced between multiple group menus
              if (isFirst) isFirst = false;
              else ; // _rootMenu.addChildAtEnd (new TextAction ());

              // get the group menu
              Vector v = getCache().getGroupMenus(new Integer(gm.getGroupId()));

              // add the group menu items to main menu
              for (int j = 0; v != null && j < v.size(); j++)
                _rootMenu.addChildAtEnd((MenuAction) v.get(j));
            }
          }
        } catch (DataSourceException e) {
          Log.error("UserState.getMenu: " + e.toString());
        }

        // add the logout entry
        _rootMenu.addChildAtEnd(new LogoutAction());
      }

      _currentMenu = _rootMenu;
    }

    return _currentMenu;
  }