@Override
  public AbsPage zPressButton(Button button) throws HarnessException {
    tracer.trace("Click button " + button);

    if (button == null) throw new HarnessException("Button cannot be null");

    AbsPage page = null;
    String locator = null;
    String subLocator = null;
    if (button == Button.B_TREE_NEWADDRESSBOOK) {

      locator = "css=div[id=main_Contacts-parent-ADDRBOOK] div[class*=ImgContextMenu]";
      subLocator = "css=div#ZmActionMenu_contacts_ADDRBOOK td#NEW_ADDRBOOK_title";
      page =
          new DialogCreateFolder(MyApplication, ((AppAjaxClient) MyApplication).zPageAddressbook);

    } else if (button == Button.B_TREE_NEWTAG) {
      // locator = zNewTagIcon;
      locator =
          "css=div[id=main_Contacts-parent-TAG] div[class*=ImgContextMenu]"; // td#ztih__main_Contacts__TAG_optCell";
      subLocator = "css=div#ZmActionMenu_contacts_TAG td#NEW_TAG_title";
      page = new DialogTag(MyApplication, ((AppAjaxClient) MyApplication).zPageAddressbook);

    } else {
      throw new HarnessException("no logic defined for button " + button);
    }

    // Default behavior, process the locator by clicking on it
    //

    // Make sure the button exists
    if (!this.sIsElementPresent(locator))
      throw new HarnessException("Button is not present locator=" + locator + " button=" + button);

    // Click it
    this.zClickAt(locator, "");

    // If the app is busy, wait for that to finish
    this.zWaitForBusyOverlay();

    // Make sure the subLocator exists
    if (!this.sIsElementPresent(subLocator))
      throw new HarnessException("Button is not present locator=" + subLocator);

    this.zClick(subLocator);

    // If the app is busy, wait for that to finish
    this.zWaitForBusyOverlay();

    // If page was specified, make sure it is active
    if (page != null) {

      // This function (default) throws an exception if never active
      page.zWaitForActive();
    }

    return (page);
  }
  /* (non-Javadoc)
   * @see framework.ui.AbsTree#zTreeItem(framework.ui.Action, framework.items.FolderItem)
   */
  public AbsPage zTreeItem(Action action, IItem addressbook) throws HarnessException {
    tracer.trace("Click " + action + " on addressbook " + addressbook);

    // Validate the arguments
    if ((action == null) || (addressbook == null)) {
      throw new HarnessException("Must define an action and addressbook");
    }
    FolderItem folder = null;
    TagItem tag = null;
    if (!(addressbook instanceof FolderItem)) {
      tag = (TagItem) addressbook;
      // throw new HarnessException("Must use FolderItem as argument, but was "+
      // addressbook.getClass());
    } else {

      folder = (FolderItem) addressbook;
    }
    AbsPage page = null;
    String locator = null;

    if (action == Action.A_LEFTCLICK) {

      // choose target addressbook to move contact to (done for TouchPad)
      locator =
          "css=div[id^='ext-tagview'] div[id^='ext-simplelistitem'] div[id^='ext-element']:contains('"
              + tag.getName()
              + "')";
      page = null;
    } else if (action == Action.A_RIGHTCLICK) {

      locator = "id=zti__main_Contacts__" + folder.getId() + "_textCell";
      if (!this.sIsElementPresent(locator)) {
        throw new HarnessException("Unable to locator folder in tree " + locator);
      }

      this.zRightClickAt(locator, "");
      zWaitForBusyOverlay();

      return (null);

    } else {
      throw new HarnessException("Action " + action + " not yet implemented");
    }

    if (locator == null) {
      throw new HarnessException("no locator defined for action: " + action);
    }

    if (!this.sIsElementPresent(locator)) {
      throw new HarnessException("Unable to locator folder in tree " + locator);
    }

    // By default, left click at locator
    zClick(locator);
    zWaitForBusyOverlay();

    if (page != null) {
      page.zWaitForActive();
    }

    return (page);
  }
  protected AbsPage zTreeItem(Action action, Button option, TagItem t) throws HarnessException {

    if ((action == null) || (option == null) || (t == null)) {
      throw new HarnessException("Must define an action, option, and addressbook");
    }
    AbsPage page = null;
    String actionLocator = null;
    String optionLocator = "css=div[id^='ZmActionMenu_contacts_TAG'] ";

    tracer.trace("processing " + t.getName());

    if (action == Action.A_LEFTCLICK) {

      throw new HarnessException("implement me!");

    } else if (action == Action.A_RIGHTCLICK) {

      actionLocator = "css=td[id^='zti__main_Contacts__']:contains('" + t.getName() + "')";
      this.zRightClickAt(actionLocator, "");

      this.zWaitForBusyOverlay();

    } else {
      throw new HarnessException("Action " + action + " not yet implemented");
    }

    if (option == Button.B_TREE_NEWTAG) {

      // optionLocator = "//td[contains(@id,'_left_icon')]/div[contains(@class,'ImgNewTag')]";
      // optionLocator="//div[contains(@id,'POPUP_DWT') and
      // contains(@class,'ZHasSubMenu')]//tbody/tr[@id='POPUP_NEW_TAG']";
      // optionLocator = css=div[id='ZmActionMenu_conversationList_TAG'] div[id='NEW_TAG']
      // td[id$='_title']
      optionLocator += " div[id^='NEW_TAG'] td[id$='_title']";

      page = new DialogTag(MyApplication, ((AppAjaxClient) MyApplication).zPageMail);

    } else if (option == Button.B_DELETE) {

      // optionLocator = Locators.zDeleteTreeMenuItem;
      optionLocator += " div[id^='DELETE_WITHOUT_SHORTCUT'] td[id$='_title']";

      page =
          new DialogWarning(
              DialogWarning.DialogWarningID.DeleteTagWarningMessage,
              MyApplication,
              ((AppAjaxClient) MyApplication).zPageAddressbook);

    } else if (option == Button.B_RENAME) {

      // optionLocator = Locators.zRenameTreeMenuItem;
      optionLocator += " div[id^='RENAME_TAG'] td[id$='_title']";

      page = new DialogRenameTag(MyApplication, ((AppAjaxClient) MyApplication).zPageAddressbook);

    } else {
      throw new HarnessException("button " + option + " not yet implemented");
    }

    if (actionLocator == null) throw new HarnessException("locator is null for action " + action);
    if (optionLocator == null) throw new HarnessException("locator is null for option " + option);

    // Default behavior. Click the locator
    zClickAt(optionLocator, "");

    // If there is a busy overlay, wait for that to finish
    this.zWaitForBusyOverlay();

    if (page != null) {

      // Wait for the page to become active, if it was specified
      page.zWaitForActive();
    }

    return (page);
  }
  protected AbsPage zTreeItem(Action action, Button option, FolderItem folderItem)
      throws HarnessException {

    AbsPage page = null;
    String actionLocator = null;
    String optionLocator = null;

    if ((action == null) || (option == null) || (folderItem == null)) {
      throw new HarnessException("Must define an action, option, and addressbook");
    }

    logger.info(
        myPageName() + " zTreeItem(" + action + ", " + option + "," + folderItem.getName() + ")");
    tracer.trace(action + " then " + option + " on Folder Item = " + folderItem.getName());

    if (folderItem.getName().equals("USER_ROOT")) {
      actionLocator = "css=div#ztih__main_Contacts__ADDRBOOK_div";
    } else {
      actionLocator = "css=div#zti__main_Contacts__" + folderItem.getId() + "_div";
    }

    if (action == Action.A_RIGHTCLICK) {

      if (option == Button.B_TREE_NEWFOLDER) {

        optionLocator =
            "css=div[id^='ZmActionMenu_contacts_ADDRBOOK'] div[id^='NEW_ADDRBOOK'] td[id$='_title']";
        page =
            new DialogCreateFolder(MyApplication, ((AppAjaxClient) MyApplication).zPageAddressbook);

      } else if (option == Button.B_DELETE) {

        optionLocator =
            "css=div[id^='ZmActionMenu_contacts_ADDRBOOK'] div[id^='DELETE_WITHOUT_SHORTCUT'] td[id$='_title']";
        page = null;

      } else if (option == Button.B_RENAME) {

        optionLocator =
            "css=div[id^='ZmActionMenu_contacts_ADDRBOOK'] div[id^='RENAME_FOLDER'] td[id$='_title']";
        page =
            new DialogRenameFolder(MyApplication, ((AppAjaxClient) MyApplication).zPageAddressbook);

      } else if (option == Button.B_TREE_EDIT) {

        optionLocator =
            "css=div[id^='ZmActionMenu_contacts_ADDRBOOK'] div[id^='EDIT_PROPS'] td[id$='_title']";
        page =
            new DialogEditFolder(MyApplication, ((AppAjaxClient) MyApplication).zPageAddressbook);

      } else if (option == Button.B_TREE_FOLDER_EMPTY) {

        optionLocator =
            "css=div[id^='ZmActionMenu_contacts_ADDRBOOK'] div[id^='EMPTY_FOLDER'] td[id$='_title']";
        page =
            new DialogWarning(
                DialogWarning.DialogWarningID.EmptyFolderWarningMessage,
                MyApplication,
                ((AppAjaxClient) MyApplication).zPageAddressbook);

      } else if (option == Button.B_SHARE) {

        optionLocator =
            "css=div[id='ZmActionMenu_contacts_ADDRBOOK'] div[id='SHARE_ADDRBOOK'] td[id$='_title']";
        page = new DialogShare(MyApplication, ((AppAjaxClient) MyApplication).zPageAddressbook);

      } else {
        throw new HarnessException("implement action:" + action + " option:" + option);
      }

      if (actionLocator != null) {

        zRightClickAt(actionLocator, "0,0");
        zWaitForBusyOverlay();
      }

      if (optionLocator != null) {

        zClickAt(optionLocator, "0,0");
        zWaitForBusyOverlay();
      }

      if (page != null) {
        page.zWaitForActive();
      }

      return page;

    } else if (action == Action.A_LEFTCLICK) {

      if (option == Button.B_TREE_NEWFOLDER) {

        zClickAt("css=div[class^=ImgNewContactsFolder][class*=ZWidget]", "0,0");
        page =
            new DialogCreateFolder(MyApplication, ((AppAjaxClient) MyApplication).zPageAddressbook);

      } else {
        throw new HarnessException("implement action:" + action + " option:" + option);
      }

    } else {
      throw new HarnessException("implement action:" + action + " option:" + option);
    }

    if (page != null) {
      page.zWaitForActive();
    }

    return page;
  }
  @Override
  public AbsPage zTreeItem(Action action, Button option, IItem item) throws HarnessException {
    // Validate the arguments
    if ((action == null) || (option == null) || (item == null)) {
      throw new HarnessException(
          "zTreeItem(Action, Button, IItem): Must define an action, option, and item");
    }

    logger.info(
        myPageName() + " zTreeItem(" + action + ", " + option + ", " + item.getName() + ")");

    tracer.trace("Click " + action + " then " + option + " on item " + item.getName());

    AbsPage page = null;
    String actionLocator = null;
    String optionLocator = null;

    if (item instanceof TagItem) {
      actionLocator =
          "css=td[id^=zti__main_Briefcase__]:contains(" + ((TagItem) item).getName() + ")";
    } else if (item instanceof FolderItem) {
      actionLocator =
          "css=td[id^=zti__main_Briefcase__" + ((FolderItem) item).getId() + "_textCell]";
    } else {
      throw new HarnessException("Must use IItem as argument, but was " + item.getClass());
    }

    zWaitForElementVisible(actionLocator);

    if (action == Action.A_RIGHTCLICK) {
      this.zRightClickAt(actionLocator, "0,0");
    } else {
      throw new HarnessException("implement me! " + action + ": not implemented");
    }

    if (option == Button.B_TREE_NEWTAG) {

      optionLocator = Locators.zNewTagTreeMenuItem;

      page = new DialogTag(MyApplication, ((AppAjaxClient) MyApplication).zPageBriefcase);

    } else if (option == Button.B_TREE_RENAMETAG) {

      optionLocator = Locators.zRenameTagTreeMenuItem;

      page = new DialogRenameTag(MyApplication, ((AppAjaxClient) MyApplication).zPageBriefcase);
    } else if (option == Button.B_TREE_DELETE) {

      optionLocator = Locators.zDeleteTreeMenuItem;

      if (item instanceof TagItem) {
        page =
            new DialogWarning(
                DialogWarning.DialogWarningID.DeleteTagWarningMessage,
                MyApplication,
                ((AppAjaxClient) MyApplication).zPageBriefcase);
      }
    } else if (option == Button.B_TREE_NEWFOLDER) {

      optionLocator = Locators.zNewFolderTreeMenuItem;

      page =
          new DialogCreateBriefcaseFolder(
              MyApplication, ((AppAjaxClient) MyApplication).zPageBriefcase);

    } else if (option == Button.B_TREE_EDIT_PROPERTIES) {

      optionLocator = Locators.zEditPropertiesTreeMenuItem;

      page =
          new DialogEditProperties(MyApplication, ((AppAjaxClient) MyApplication).zPageBriefcase);

    } else {
      throw new HarnessException("button " + option + " not yet implemented");
    }

    this.zWaitForBusyOverlay();

    zWaitForElementVisible(optionLocator);

    // Default behavior. Click the locator
    zClickAt(optionLocator, "");

    // If there is a busy overlay, wait for that to finish
    this.zWaitForBusyOverlay();

    if (page != null) {
      // Wait for the page to become active, if it was specified
      page.zWaitForActive();
    }
    return (page);
  }
  public AbsPage zPressPulldown(Button pulldown, Button option) throws HarnessException {
    logger.info(myPageName() + " zPressPulldown(" + pulldown + ", " + option + ")");

    tracer.trace("Click " + pulldown + " then " + option);

    if (pulldown == null) throw new HarnessException("Pulldown cannot be null");

    if (option == null) throw new HarnessException("Option cannot be null");

    AbsPage page = null;
    String pulldownLocator = null;
    String optionLocator = null;

    if (pulldown == Button.B_TREE_FOLDERS_OPTIONS) {

      pulldownLocator =
          "css=div[id='ztih__main_Briefcase__BRIEFCASE_div'] td[id='ztih__main_Briefcase__BRIEFCASE_optCell'] div[class=ImgContextMenu]";

      if (option == Button.B_TREE_NEWFOLDER) {

        optionLocator =
            "css=div[id='ZmActionMenu_briefcase_BRIEFCASE'] div[id='NEW_BRIEFCASE'] td[id$='_title']";
        page =
            new DialogCreateBriefcaseFolder(
                MyApplication, ((AppAjaxClient) MyApplication).zPageBriefcase);

      } else {
        throw new HarnessException(
            "Pulldown/Option " + pulldown + "/" + option + " not implemented");
      }

      // FALL THROUGH

    } else if (pulldown == Button.B_TREE_TAGS_OPTIONS) {

      pulldownLocator =
          "css=div[id='zov__main_Briefcase'] td[id='ztih__main_Briefcase__TAG_optCell'] div[class=ImgContextMenu]";

      if (option == Button.B_TREE_NEWTAG) {

        optionLocator =
            "css=div[id='ZmActionMenu_briefcase_TAG'] div[id='NEW_TAG'] td[id$='_title']";
        page = new DialogTag(MyApplication, ((AppAjaxClient) MyApplication).zPageBriefcase);

      } else {
        throw new HarnessException(
            "Pulldown/Option " + pulldown + "/" + option + " not implemented");
      }

      // FALL THROUGH

    } else {
      throw new HarnessException("Pulldown/Option " + pulldown + "/" + option + " not implemented");
    }

    // Default behavior
    if (pulldownLocator != null) {

      // Make sure the locator exists
      if (!this.sIsElementPresent(pulldownLocator)) {
        throw new HarnessException(
            "Button "
                + pulldown
                + " option "
                + option
                + " pulldownLocator "
                + pulldownLocator
                + " not present!");
      }

      // 8.0 change ... need zClickAt()
      // this.zClick(pulldownLocator);
      this.zClickAt(pulldownLocator, "0,0");

      // If the app is busy, wait for it to become active
      zWaitForBusyOverlay();

      if (optionLocator != null) {

        // Make sure the locator exists
        if (!this.sIsElementPresent(optionLocator)) {
          throw new HarnessException(
              "Button "
                  + pulldown
                  + " option "
                  + option
                  + " optionLocator "
                  + optionLocator
                  + " not present!");
        }

        // 8.0 change ... need zClickAt()
        // this.zClick(optionLocator);
        this.zClickAt(optionLocator, "0,0");

        // If the app is busy, wait for it to become active
        zWaitForBusyOverlay();
      }

      // If we click on pulldown/option and the page is specified, then
      // wait for the page to go active
      if (page != null) {
        page.zWaitForActive();
      }
    }

    // Return the specified page, or null if not set
    return (page);
  }
  @Override
  public AbsPage zPressButton(Button button) throws HarnessException {
    tracer.trace("Click " + button);

    if (button == null) throw new HarnessException("Button cannot be null");

    AbsPage page = null;
    String locator = null;

    if (button == Button.B_TREE_NEWBRIEFCASE) {

      locator = "css=div[id=ztih__main_Briefcase__BRIEFCASE] div[class^=ImgNewFolder ZWidget]";
      page =
          new DialogCreateBriefcaseFolder(
              MyApplication, ((AppAjaxClient) MyApplication).zPageBriefcase);

      if (!this.sIsElementPresent(locator)) {
        throw new HarnessException("Unable to locate folder in the tree " + locator);
      }

      this.zClickAt(locator, "0,0");

      zWaitForBusyOverlay();

      return page;

    } else if (button == Button.B_TREE_NEWTAG) {

      locator = "css=div[class^=ImgNewTag ZWidget]";

      if (!this.sIsElementPresent(locator)) {
        throw new HarnessException("Unable to locate folder in tree " + locator);
      }
      page = new DialogTag(MyApplication, ((AppAjaxClient) MyApplication).zPageBriefcase);
    } else if (button == Button.B_TREE_BRIEFCASE_EXPANDCOLLAPSE) {

      locator = null;
      page = null;

      // TODO: implement me

      // FALL THROUGH
    } else {
      throw new HarnessException("no logic defined for button " + button);
    }

    if (locator == null) {
      throw new HarnessException("locator was null for button " + button);
    }

    // Default behavior, process the locator by clicking on it
    //

    // Click it
    this.zClickAt(locator, "0,0");

    // If the app is busy, wait for that to finish
    zWaitForBusyOverlay();

    // If page was specified, make sure it is active
    if (page != null) {

      // This function (default) throws an exception if never active
      page.zWaitForActive();
    }
    return (page);
  }