protected static String getConcernNameWithMnemonic(
      Concern concern, Set<Character> mnemonicsAlreadyUsed) {
    String concernName = concern.getDisplayName();
    assert concernName != null && !concernName.isEmpty();

    if (concernName.indexOf('&') >= 0) return concernName;

    char[] buf = concernName.toCharArray();

    char[] newBuf = new char[buf.length + 1]; // Add one for the ampersand

    for (int i = 0, newIndex = 0; i < buf.length; ++i, ++newIndex) {
      char c = buf[i];

      if ((newIndex == i)
          && Character.isLetter(c)
          && mnemonicsAlreadyUsed.add(c)) // Returns true if mnemonic doesn't exist
      {
        newBuf[newIndex++] = '&';
      }

      newBuf[newIndex] = c;
    }

    return new String(newBuf);
  }
  protected static boolean isLinked(
      Concern concern, List<IJavaElement> javaElements, EdgeKind concernComponentRelation) {
    // See if any of the selected elements are already
    // linked to the concern
    for (IJavaElement javaElement : javaElements) {
      if (concern.isLinked(javaElement, concernComponentRelation)) {
        return true;
      }
    }

    return false;
  }
  /** Builds the cascading 'Link' menu */
  private void fillMenuRecursive(
      Menu parent,
      List<Concern> concerns,
      List<IJavaElement> selectedJavaElements,
      EdgeKind concernComponentRelation) {
    Set<Character> mnemonicsUsed = new HashSet<Character>();

    for (Concern concern : concerns) {
      // See if any of the selected elements are already
      // linked to the concern
      getSelectedJavaElements(
          aJavaEditor, FLATTT.tableView.getViewer().getSelection(), selectedJavaElements);
      boolean isLinked = isLinked(concern, selectedJavaElements, concernComponentRelation);

      // For the 'Unlink' menu, only show linked concerns

      if (isLinked) {
        MenuItem lMenuItem = new MenuItem(parent, SWT.PUSH);
        lMenuItem.setData(concern);
        lMenuItem.setText(getConcernNameWithMnemonic(concern, mnemonicsUsed));
        lMenuItem.addSelectionListener(clickListener);
      }

      List<Concern> children = concern.getChildren();

      if (!children.isEmpty()) {
        // The 'Unlink' menu is flat, so we pass in the same
        // parent menu

        fillMenuRecursive(parent, children, selectedJavaElements, concernComponentRelation);
      }

      children = null; // Helps GC
      /*
      List<Concern> children = concern.getChildren();

      MenuItem lMenuItem = null;
      Menu childMenu = null;

      // For the 'Link' menu, create menu items for all concerns,
      // regardless of whether they are linked.

      // See if we already created the item
      for(MenuItem menuItem : parent.getItems())
      {
      	Object data = menuItem.getData();
      	if (data != null &&
      		data.equals(concern))
      	{
      		lMenuItem = menuItem;
      		childMenu = lMenuItem.getMenu();
      		break;
      	}
      }

      // Lazily create the concern menu item
      if (lMenuItem == null)
      {
      	if (!children.isEmpty())
      	{
      		lMenuItem = new MenuItem(parent, SWT.CASCADE);
      	}
      	else
      	{
      		lMenuItem = new MenuItem(parent, SWT.PUSH);

      		// Can't click on cascading menu
      		lMenuItem.addSelectionListener(clickListener);
      	}

      	lMenuItem.setData(concern);
      	lMenuItem.setText(getConcernNameWithMnemonic(concern, mnemonicsUsed));
      }

      lMenuItem.setEnabled(!children.isEmpty() || isLinked);

      if (!children.isEmpty())
      {
      	// The 'Link' menu is hierarchical, so we create
      	// a cascading menu for the children

      	assert lMenuItem != null;

      	if (childMenu == null)
      	{
      		childMenu = new Menu(lMenuItem);
      	}

      	fillMenuRecursive(childMenu, children, selectedJavaElements,
      			concernComponentRelation);

      	lMenuItem.setMenu(childMenu);
      }

      children = null; // Helps GC*/
    }

    mnemonicsUsed = null; // Helps GC
  }