@Override
  protected void encodeHiddenAttributes(
      FacesContext facesContext, ResponseWriter responseWriter, InputFile inputFile, boolean first)
      throws IOException {

    // fileFieldName
    encodeString(responseWriter, "fileFieldName", inputFile.getClientId(), first);
    first = false;

    // multipleFiles
    String multiple = inputFile.getMultiple();
    boolean multipleFiles = "multiple".equalsIgnoreCase(multiple);
    encodeBoolean(responseWriter, "multipleFiles", multipleFiles, first);

    // selectFilesButton
    Locale locale = facesContext.getViewRoot().getLocale();
    String chooseFiles = getMessageContext().getMessage(locale, "choose-files");
    StringBuilder selectFilesButtonScript = new StringBuilder();
    selectFilesButtonScript.append(
        "A.Node.create(\"<button type='button' class='alloy-button' role='button' aria-label='");
    selectFilesButtonScript.append(chooseFiles);
    selectFilesButtonScript.append("' tabindex='{tabIndex}'>");
    selectFilesButtonScript.append(chooseFiles);
    selectFilesButtonScript.append("</button>\")");
    encodeNonEscapedObject(responseWriter, "selectFilesButton", selectFilesButtonScript, first);
  }
  protected void encodePreview(
      FacesContext facesContext, ResponseWriter responseWriter, InputFile inputFile)
      throws IOException {

    // Delegate writing of the entire <input type="file"...> ... </input> element to the delegate
    // renderer.
    DelegationResponseWriter delegationResponseWriter =
        new InputFileDelegationResponseWriter(responseWriter, inputFile.isAuto());
    super.encodeMarkupEnd(facesContext, inputFile, delegationResponseWriter);

    // Format the preview-table.html template and write it to the response.
    Locale locale = facesContext.getViewRoot().getLocale();
    String clientId = inputFile.getClientId(facesContext);
    responseWriter.startElement("div", inputFile);
    responseWriter.startElement("table", inputFile);
    responseWriter.writeAttribute("id", clientId + "_table", null);
    responseWriter.writeAttribute("class", "table table-bordered", null);
    responseWriter.startElement("thead", inputFile);
    responseWriter.writeAttribute("class", "table-columns", null);
    responseWriter.startElement("tr", inputFile);
    responseWriter.startElement("th", inputFile);

    MessageContextFactory messageContextFactory =
        (MessageContextFactory) FactoryExtensionFinder.getFactory(MessageContextFactory.class);
    MessageContext messageContext = messageContextFactory.getMessageContext();
    String i18nFileName = messageContext.getMessage(locale, "file-name");
    responseWriter.writeText(i18nFileName, null);
    responseWriter.endElement("th");
    responseWriter.startElement("th", inputFile);

    String i18nFileType = messageContext.getMessage(locale, "file-type");
    responseWriter.writeText(i18nFileType, null);
    responseWriter.endElement("th");
    responseWriter.startElement("th", inputFile);

    String i18nFileSize = messageContext.getMessage(locale, "file-size");
    responseWriter.writeText(i18nFileSize, null);
    responseWriter.endElement("th");
    responseWriter.endElement("tr");
    responseWriter.endElement("thead");
    responseWriter.startElement("tfoot", inputFile);
    responseWriter.startElement("tr", inputFile);
    responseWriter.startElement("td", inputFile);
    responseWriter.writeAttribute("colspan", "3", null);

    String i18nNoFilesSelected = messageContext.getMessage(locale, "no-files-selected");
    responseWriter.writeText(i18nNoFilesSelected, null);
    responseWriter.endElement("td");
    responseWriter.endElement("tr");
    responseWriter.endElement("tfoot");
    responseWriter.startElement("tbody", inputFile);
    responseWriter.startElement("tr", inputFile);
    responseWriter.endElement("tr");
    responseWriter.endElement("tbody");
    responseWriter.endElement("table");
    responseWriter.endElement("div");
  }
  @Override
  public void encodeJavaScriptCustom(FacesContext facesContext, UIComponent uiComponent)
      throws IOException {

    ResponseWriter responseWriter = facesContext.getResponseWriter();
    InputFile inputFile = (InputFile) uiComponent;
    JavaScriptFragment alloyNamespace = new JavaScriptFragment("A");

    // Determine the valid content-types and maximum file size from the validator (if specified).
    JavaScriptFragment contentTypes = new JavaScriptFragment("[]");
    String validContentTypes = inputFile.getContentTypes();

    if (validContentTypes != null) {
      contentTypes = toJavaScriptArray(validContentTypes.split(","));
    }

    String clientId = inputFile.getClientId(facesContext);
    Long maxFileSize = inputFile.getMaxFileSize();

    if (maxFileSize == null) {
      maxFileSize = Long.MAX_VALUE;
    }

    // If the component should render the upload progress table, then initialize the YUI progress
    // uploader widget.
    if (inputFile.isShowProgress()) {

      String clientVarName = getClientVarName(facesContext, inputFile);
      String clientKey = inputFile.getClientKey();

      if (clientKey == null) {
        clientKey = clientVarName;
      }

      UIViewRoot viewRoot = facesContext.getViewRoot();
      Locale locale = viewRoot.getLocale();
      String formClientId = getParentFormClientId(inputFile);
      Application application = facesContext.getApplication();
      ViewHandler viewHandler = application.getViewHandler();
      String actionURL = viewHandler.getActionURL(facesContext, viewRoot.getViewId());
      String partialActionURL = facesContext.getExternalContext().encodePartialActionURL(actionURL);
      String namingContainerId = "";

      if (viewRoot instanceof NamingContainer) {
        namingContainerId = viewRoot.getContainerClientId(facesContext);
      }

      AjaxParameters ajaxParameters = new AjaxParameters(inputFile, clientId, formClientId);
      String execute = ajaxParameters.getExecute();
      String render = ajaxParameters.getRender();

      String notStartedMessage = getMessageContext().getMessage(locale, "not-started");
      JavaScriptFragment clientComponent =
          new JavaScriptFragment("Liferay.component('" + clientKey + "')");
      encodeFunctionCall(
          responseWriter,
          "LFAI.initProgressUploader",
          alloyNamespace,
          clientComponent,
          contentTypes,
          clientId,
          formClientId,
          namingContainerId,
          inputFile.isAuto(),
          execute,
          render,
          partialActionURL,
          maxFileSize,
          notStartedMessage);
    }

    // Otherwise, if the component should render the upload preview table, then format the
    // preview-uploader.js
    // template and write it to the response.
    else if (inputFile.isShowPreview()) {

      encodeFunctionCall(
          responseWriter,
          "LFAI.initPreviewUploader",
          alloyNamespace,
          contentTypes,
          clientId,
          maxFileSize);
    }
  }