public void renderLink(
      Appendable writer, Map<String, Object> context, ModelScreenWidget.Link link)
      throws IOException {
    HttpServletResponse response = (HttpServletResponse) context.get("response");
    HttpServletRequest request = (HttpServletRequest) context.get("request");

    String targetWindow = link.getTargetWindow(context);
    String target = link.getTarget(context);

    String uniqueItemName =
        link.getModelScreen().getName()
            + "_LF_"
            + UtilMisc.<String>addToBigDecimalInMap(
                context, "screenUniqueItemIndex", BigDecimal.ONE);

    String linkType =
        WidgetWorker.determineAutoLinkType(link.getLinkType(), target, link.getUrlMode(), request);
    String linkUrl = "";
    String actionUrl = "";
    StringBuilder parameters = new StringBuilder();
    String width = link.getWidth();
    if (UtilValidate.isEmpty(width)) {
      width = "300";
    }
    String height = link.getHeight();
    if (UtilValidate.isEmpty(height)) {
      height = "200";
    }
    if ("hidden-form".equals(linkType) || "ajax-window".equals(linkType)) {
      StringBuilder sb = new StringBuilder();
      WidgetWorker.buildHyperlinkUrl(
          sb,
          target,
          link.getUrlMode(),
          null,
          link.getPrefix(context),
          link.getFullPath(),
          link.getSecure(),
          link.getEncode(),
          request,
          response,
          context);
      actionUrl = sb.toString();
      parameters.append("[");
      for (Map.Entry<String, String> parameter : link.getParameterMap(context).entrySet()) {
        if (parameters.length() > 1) {
          parameters.append(",");
        }
        parameters.append("{'name':'");
        parameters.append(parameter.getKey());
        parameters.append("'");
        parameters.append(",'value':'");
        parameters.append(parameter.getValue());
        parameters.append("'}");
      }
      parameters.append("]");
    }
    String id = link.getId(context);
    String style = link.getStyle(context);
    String name = link.getName(context);
    String text = link.getText(context);
    if (UtilValidate.isNotEmpty(target)) {
      if (!"hidden-form".equals(linkType)) {
        StringBuilder sb = new StringBuilder();
        WidgetWorker.buildHyperlinkUrl(
            sb,
            target,
            link.getUrlMode(),
            link.getParameterMap(context),
            link.getPrefix(context),
            link.getFullPath(),
            link.getSecure(),
            link.getEncode(),
            request,
            response,
            context);
        linkUrl = sb.toString();
      }
    }
    String imgStr = "";
    ModelScreenWidget.Image img = link.getImage();
    if (img != null) {
      StringWriter sw = new StringWriter();
      renderImage(sw, context, img);
      imgStr = sw.toString();
    }
    StringWriter sr = new StringWriter();
    sr.append("<@renderLink ");
    sr.append("parameterList=");
    sr.append(parameters.length() == 0 ? "\"\"" : parameters.toString());
    sr.append(" targetWindow=\"");
    sr.append(targetWindow);
    sr.append("\" target=\"");
    sr.append(target);
    sr.append("\" uniqueItemName=\"");
    sr.append(uniqueItemName);
    sr.append("\" linkType=\"");
    sr.append(linkType);
    sr.append("\" actionUrl=\"");
    sr.append(actionUrl);
    sr.append("\" id=\"");
    sr.append(id);
    sr.append("\" style=\"");
    sr.append(style);
    sr.append("\" name=\"");
    sr.append(name);
    sr.append("\" width=\"");
    sr.append(width);
    sr.append("\" height=\"");
    sr.append(height);
    sr.append("\" linkUrl=\"");
    sr.append(linkUrl);
    sr.append("\" text=\"");
    sr.append(text);
    sr.append("\" imgStr=\"");
    sr.append(imgStr.replaceAll("\"", "\\\\\""));
    sr.append("\" />");
    executeMacro(writer, sr.toString());
  }
 @Override
 public void renderLink(Appendable writer, Map<String, Object> context, MenuLink link)
     throws IOException {
   Map<String, Object> parameters = new HashMap<String, Object>();
   String target = link.getTarget(context);
   ModelMenuItem menuItem = link.getLinkMenuItem();
   if (isDisableIfEmpty(menuItem, context)) {
     target = null;
   }
   parameters.put("id", link.getId(context));
   parameters.put("style", link.getStyle(context));
   parameters.put("name", link.getName(context));
   parameters.put("text", link.getText(context));
   parameters.put("targetWindow", link.getTargetWindow(context));
   String uniqueItemName =
       menuItem.getModelMenu().getName()
           + "_"
           + menuItem.getName()
           + "_LF_"
           + UtilMisc.<String>addToBigDecimalInMap(context, "menuUniqueItemIndex", BigDecimal.ONE);
   if (menuItem.getModelMenu().getExtraIndex(context) != null) {
     uniqueItemName += "_" + menuItem.getModelMenu().getExtraIndex(context);
   }
   parameters.put("uniqueItemName", uniqueItemName);
   String linkType = "";
   if (UtilValidate.isNotEmpty(target)) {
     linkType =
         WidgetWorker.determineAutoLinkType(
             link.getLinkType(), target, link.getUrlMode(), request);
   }
   parameters.put("linkType", linkType);
   String linkUrl = "";
   String actionUrl = "";
   StringBuilder targetParameters = new StringBuilder();
   if ("hidden-form".equals(linkType) || "ajax-window".equals(linkType)) {
     StringBuilder sb = new StringBuilder();
     WidgetWorker.buildHyperlinkUrl(
         sb,
         target,
         link.getUrlMode(),
         null,
         link.getPrefix(context),
         link.getFullPath(),
         link.getSecure(),
         link.getEncode(),
         request,
         response,
         context);
     actionUrl = sb.toString();
     targetParameters.append("[");
     for (Map.Entry<String, String> parameter : link.getParameterMap(context).entrySet()) {
       if (targetParameters.length() > 1) {
         targetParameters.append(",");
       }
       targetParameters.append("{'name':'");
       targetParameters.append(parameter.getKey());
       targetParameters.append("'");
       targetParameters.append(",'value':'");
       targetParameters.append(parameter.getValue());
       targetParameters.append("'}");
     }
     targetParameters.append("]");
   }
   if (targetParameters.length() == 0) {
     targetParameters.append("\"\"");
   }
   if (UtilValidate.isNotEmpty(target)) {
     if (!"hidden-form".equals(linkType)) {
       StringBuilder sb = new StringBuilder();
       WidgetWorker.buildHyperlinkUrl(
           sb,
           target,
           link.getUrlMode(),
           link.getParameterMap(context),
           link.getPrefix(context),
           link.getFullPath(),
           link.getSecure(),
           link.getEncode(),
           request,
           response,
           context);
       linkUrl = sb.toString();
     }
   }
   parameters.put("linkUrl", linkUrl);
   parameters.put("actionUrl", actionUrl);
   parameters.put("parameterList", targetParameters);
   String imgStr = "";
   Image img = link.getImage();
   if (img != null) {
     StringWriter sw = new StringWriter();
     renderImage(sw, context, img);
     imgStr = sw.toString();
   }
   parameters.put("imgStr", imgStr);
   try {
     executeMacro(writer, "renderLink", parameters);
   } catch (TemplateException e) {
     throw new IOException(e);
   }
 }