@Override
  public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
    if (!component.isRendered()) {
      return;
    }

    // Get the response renderer
    ResponseWriter writer = context.getResponseWriter();

    // Do not render if it is not needed
    if (AjaxUtil.isAjaxNullResponseWriter(writer)) {
      return;
    }

    // Get the UIInput
    if (!(component instanceof UIInput)) {
      return;
    }
    UIInput uiInput = (UIInput) component;

    // And write the value
    String currentValue = computeValueAsISOString(context, uiInput);
    writeTag(context, uiInput, writer, currentValue);

    // TODO should change this to use InputRendererUtil.encodeValidation,
    // once it has been updated to support delegating to the renderer.
    //        InputRendererUtil.encodeValidation(context, writer, uiInput);
    encodeValidation(context, writer, uiInput);

    InputRendererUtil.encodeDirtyState(context, writer, uiInput);
  }
  // === continue code from InputRendererUtil ===
  // ClientSide validation
  // com.ibm.xsp.renderkit.html_basic.InputRendererUtil.generateClientSideValidation(FacesContext,
  // UIInput, ResponseWriter)
  private void generateClientSideValidation(
      FacesContext context, UIInput uiInput, ResponseWriter writer) throws IOException {
    // Check if the input field is required
    boolean required = uiInput.isRequired();
    Converter c = InputRendererUtil.findConverter(context, uiInput);
    Validator[] v = uiInput.getValidators();

    // Check if it might make sense to generate a function
    boolean validate = required;
    if (!validate) {
      validate = c instanceof ClientSideConverter;
    }
    if (!validate) {
      for (int i = 0; i < v.length; i++) {
        validate = v[i] instanceof ClientSideValidator;
        if (validate) {
          break;
        }
      }
    }

    if (validate) {
      // This flag is maintained if we actually need to generate the function
      // Some converter/validator may not actually generate any client code, depending on their
      // parameters
      validate = false;

      StringBuilder b = new StringBuilder(128);
      b.append("XSP.attachValidator("); // $NON-NLS-1$
      JavaScriptUtil.addString(b, uiInput.getClientId(context));

      // Add the required flag
      if (required) {
        b.append(",new XSP.RequiredValidator("); // $NON-NLS-1$
        JavaScriptUtil.addMessage(b, InputRendererUtil.getRequiredMessage(context, uiInput));
        b.append(")");
        validate = true;
      } else {
        b.append(",null"); // $NON-NLS-1$
      }

      // Add the converter
      if (c instanceof ClientSideConverter) {
        ClientSideConverter clientSideConverter = (ClientSideConverter) c;
        // TODO this is handling of converterRenderer
        // differs from the original implementation in InputRendererUtil.
        String s;
        Renderer renderer =
            FacesUtil.getRenderer(context, uiInput.getFamily(), uiInput.getRendererType());
        ClientSideConverter converterRenderer =
            (ClientSideConverter) FacesUtil.getRendererAs(renderer, ClientSideConverter.class);
        if (null != converterRenderer) {
          // if the control renderer implements ClientSideConverter
          // delegate to the renderer instead of to the converter.
          s = converterRenderer.generateClientSideConverter(context, uiInput);
        } else {
          s = clientSideConverter.generateClientSideConverter(context, uiInput);
        }
        if (StringUtil.isNotEmpty(s)) {
          b.append(",");
          b.append(s); // not JSUtil because contains client script.
          validate = true;
        } else {
          b.append(",null"); // $NON-NLS-1$
        }
      } else {
        b.append(",null"); // $NON-NLS-1$
      }

      // And add the validator
      for (int i = 0; i < v.length; i++) {
        if (v[i] instanceof ClientSideValidator) {
          String s = ((ClientSideValidator) v[i]).generateClientSideValidation(context, uiInput);
          if (StringUtil.isNotEmpty(s)) {
            b.append(",");
            b.append(s); // not JSUtil because contains client script.
            validate = true;
          }
        }
      }

      // Finally, check for multiple values
      String multiSep = null;
      if (uiInput instanceof UIInputEx) {
        multiSep = ((UIInputEx) uiInput).getMultipleSeparator();
      }
      if (c instanceof ListConverter) {
        multiSep = ((ListConverter) c).getDelimiter();
        if (StringUtil.isEmpty(multiSep)) {
          multiSep = ","; // $NON-NLS-1$
        }
      }
      if (StringUtil.isNotEmpty(multiSep)) {
        b.append(",");
        JSUtil.addString(b, multiSep);
      }

      b.append(");");

      // get the scriptcollector component (needed to add script blocks the the rendered output).
      if (validate) {
        JavaScriptUtil.addScriptOnLoad(b.toString());
      }
    }
  }