@Override
  public List<TemplateHandler> getPortletDisplayTemplateHandlers() {
    List<TemplateHandler> templateHandlers = TemplateHandlerRegistryUtil.getTemplateHandlers();

    List<TemplateHandler> portletDisplayTemplateHandlers = new ArrayList<>();

    for (TemplateHandler templateHandler : templateHandlers) {
      if (templateHandler instanceof BasePortletDisplayTemplateHandler) {
        portletDisplayTemplateHandlers.add(templateHandler);
      } else if (ProxyUtil.isProxyClass(templateHandler.getClass())) {
        InvocationHandler invocationHandler = ProxyUtil.getInvocationHandler(templateHandler);

        if (invocationHandler instanceof ClassLoaderBeanHandler) {
          ClassLoaderBeanHandler classLoaderBeanHandler =
              (ClassLoaderBeanHandler) invocationHandler;

          Object bean = classLoaderBeanHandler.getBean();

          if (bean instanceof BasePortletDisplayTemplateHandler) {
            portletDisplayTemplateHandlers.add(templateHandler);
          }
        }
      }
    }

    return portletDisplayTemplateHandlers;
  }
  @Override
  public DDMTemplate getDefaultPortletDisplayTemplateDDMTemplate(long groupId, long classNameId) {

    TemplateHandler templateHandler = TemplateHandlerRegistryUtil.getTemplateHandler(classNameId);

    if ((templateHandler == null) || (templateHandler.getDefaultTemplateKey() == null)) {

      return null;
    }

    return getPortletDisplayTemplateDDMTemplate(
        groupId, classNameId, getDisplayStyle(templateHandler.getDefaultTemplateKey()));
  }
  @Override
  public String renderDDMTemplate(
      HttpServletRequest request,
      HttpServletResponse response,
      DDMTemplate ddmTemplate,
      List<?> entries,
      Map<String, Object> contextObjects)
      throws Exception {

    Transformer transformer = TransformerHolder.getTransformer();

    contextObjects.put(PortletDisplayTemplateConstants.TEMPLATE_ID, ddmTemplate.getTemplateId());
    contextObjects.put(PortletDisplayTemplateConstants.ENTRIES, entries);

    if (!entries.isEmpty()) {
      contextObjects.put(PortletDisplayTemplateConstants.ENTRY, entries.get(0));
    }

    contextObjects.put(PortletDisplayTemplateConstants.LOCALE, request.getLocale());

    contextObjects.put(PortletDisplayTemplateConstants.REQUEST, request);

    RenderRequest renderRequest =
        (RenderRequest) request.getAttribute(JavaConstants.JAVAX_PORTLET_REQUEST);

    contextObjects.put(PortletDisplayTemplateConstants.RENDER_REQUEST, renderRequest);

    RenderResponse renderResponse =
        (RenderResponse) request.getAttribute(JavaConstants.JAVAX_PORTLET_RESPONSE);

    contextObjects.put(PortletDisplayTemplateConstants.RENDER_RESPONSE, renderResponse);

    if ((renderRequest != null) && (renderResponse != null)) {
      PortletURL currentURL = PortletURLUtil.getCurrent(renderRequest, renderResponse);

      contextObjects.put(PortletDisplayTemplateConstants.CURRENT_URL, currentURL.toString());
    }

    ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);

    contextObjects.put(PortletDisplayTemplateConstants.THEME_DISPLAY, themeDisplay);

    // Custom context objects

    contextObjects.put(TemplateConstants.CLASS_NAME_ID, ddmTemplate.getClassNameId());

    String language = ddmTemplate.getLanguage();

    TemplateManager templateManager = TemplateManagerUtil.getTemplateManager(language);

    TemplateHandler templateHandler =
        TemplateHandlerRegistryUtil.getTemplateHandler(ddmTemplate.getClassNameId());

    templateManager.addContextObjects(contextObjects, templateHandler.getCustomContextObjects());

    // Taglibs

    templateManager.addTaglibApplication(
        contextObjects,
        PortletDisplayTemplateConstants.FREEMARKER_SERVLET_APPLICATION,
        request.getServletContext());

    templateManager.addTaglibRequest(
        contextObjects,
        PortletDisplayTemplateConstants.FREEMARKER_SERVLET_REQUEST,
        request,
        response);

    templateManager.addTaglibFactory(
        contextObjects,
        PortletDisplayTemplateConstants.TAGLIB_LIFERAY_HASH,
        request.getServletContext());

    UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();

    templateManager.addTaglibTheme(
        contextObjects,
        "taglibLiferay",
        request,
        new PipingServletResponse(response, unsyncStringWriter));

    contextObjects.put(TemplateConstants.WRITER, unsyncStringWriter);

    if (renderRequest != null) {
      contextObjects.putAll(_getPortletPreferences(renderRequest));
    }

    return transformer.transform(
        themeDisplay, contextObjects, ddmTemplate.getScript(), language, unsyncStringWriter);
  }