/**
   * Print the icon and text for navigating the hierarchy on the team side using frames and relative
   * paths
   */
  private void writeHierarchyIconFrame(String prefix, String projectRoot) {
    String href = WebServer.urlEncodePath(projectRoot) + "//team/setup/selectWBSFrame.class";
    writeHyperlink(href, getSnippetParams(true, true));

    out.print(
        "<img border=0 src='/Images/hier.png' "
            + "title='Drill-down in Hierarchy' "
            + "style='margin-right:2px' width=16 height=23></a>");
    if (prefix.equals(projectRoot)) out.print("/");
    else out.print(HTMLUtils.escapeEntities(prefix.substring(projectRoot.length() + 1)));
  }
  private void writeHierarchyIconNonFrame(String projectRoot, String uri) {
    String pathDisplay = "/";
    SimpleData wbsData = getDataContext().getSimpleValue("Project_WBS_ID_Filter");
    if (wbsData != null) {
      pathDisplay = wbsData.format();
      int slashPos = pathDisplay.indexOf('/');
      if (slashPos == -1) pathDisplay = "/";
      else pathDisplay = pathDisplay.substring(slashPos + 1);
    }

    boolean exporting = parameters.containsKey("EXPORT");
    if (!exporting) {
      String href = WebServer.urlEncodePath(projectRoot) + "//team/setup/" + uri;
      writeHyperlink(href, getSnippetParams(false, false));
    }

    out.print(
        "<img border=0 src='/Images/hier.png' "
            + "style='margin-right:2px' width='16' height='23' ");
    if (!exporting) out.print("title='Drill-down in Hierarchy'></a>");
    else if ("/".equals(pathDisplay))
      out.print("title='Showing data from entire project hierarchy'>");
    else out.print("title='Hierarchy Drill-down is in effect'>");

    out.print(HTMLUtils.escapeEntities(pathDisplay));

    String dashVersion = (String) env.get("Dash_Package_pspdash");
    if (!exporting && VersionUtils.compareVersions(dashVersion, "1.15.2") > 0) {
      // this is a single rollup with a single data-driven filter. If
      // two pages are open to the same report, a filter change in one
      // will affect the data in the other. Add "active" data elements
      // to the page that will trigger a refresh in that scenario.
      // (Note that we only do this for version 1.15.3 and higher,
      // because this can trigger an infinite reload loop in earlier
      // versions of the dashboard.)
      out.print("<input type='hidden' name='[Project_WBS_ID_Filter]!'>");
      out.print("<input type='hidden' name='[Label//Filter]!'>");
    }
  }
  private void repairMasterProjectLinks() {
    if (!StringUtils.hasValue(masterPrefix)) return;

    String masterTagDataName = masterPrefix + "/" + processID + " Master Root Tag";
    Object tag = ctx.getData().getSimpleValue(masterTagDataName);
    if (!(tag instanceof TagData)) {
      couldNotRepairMasterLinks();
      return;
    }

    String url =
        WebServer.DASHBOARD_PROTOCOL
            + ":"
            + WebServer.urlEncodePath(masterPrefix)
            + "//"
            + processID
            + "/setup/subprojectEdit?do=update";
    try {
      InputStream in = new URL(url).openStream();
      while (in.read() != -1) ;
    } catch (Exception e) {
      couldNotRepairMasterLinks();
    }
  }