@Override
  public List<String> update(
      List<FileItem> items, Field field, FieldTemplate template, PagesContext pageContext)
      throws FormException {
    List<String> attachmentIds = new ArrayList<String>();

    try {
      String fieldName = template.getFieldName();
      String attachmentId = uploadVideoFile(items, fieldName, pageContext);
      Operation operation =
          Operation.valueOf(FileUploadUtil.getParameter(items, fieldName + OPERATION_KEY));
      String currentAttachmentId =
          FileUploadUtil.getParameter(items, fieldName + Field.FILE_PARAM_NAME_SUFFIX);
      if (isDeletion(operation, currentAttachmentId) || isUpdate(operation, attachmentId)) {
        deleteAttachment(currentAttachmentId, pageContext);
      }
      if (StringUtil.isDefined(attachmentId)) {
        attachmentIds.addAll(update(attachmentId, field, template, pageContext));
      }
    } catch (Exception ex) {
      SilverTrace.error("form", "VideoFieldDisplayer.update", "form.EXP_UNKNOWN_FIELD", null, ex);
    }

    return attachmentIds;
  }
  /**
   * Prints the javascripts which will be used to control the new value given to the named field.
   * The error messages may be adapted to a local language. The FieldTemplate gives the field type
   * and constraints. The FieldTemplate gives the local labeld too. Never throws an Exception but
   * log a silvertrace and writes an empty string when :
   *
   * <UL>
   *   <LI>the fieldName is unknown by the template.
   *   <LI>the field type is not a managed type.
   * </UL>
   *
   * @param out
   * @param template
   * @param PagesContext
   * @throws java.io.IOException
   */
  @Override
  public void displayScripts(PrintWriter out, FieldTemplate template, PagesContext PagesContext)
      throws java.io.IOException {
    String language = PagesContext.getLanguage();
    if (!TextField.TYPE.equals(template.getTypeName())) {
      SilverTrace.info(
          "form",
          "TimeFieldDisplayer.displayScripts",
          "form.INFO_NOT_CORRECT_TYPE",
          TextField.TYPE);
    }

    out.println(
        "var "
            + template.getFieldName()
            + "Empty = isWhitespace(stripInitialWhitespace(field.value));");

    if (template.isMandatory() && PagesContext.useMandatory()) {
      out.println("	if (" + template.getFieldName() + "Empty) {");
      out.println(
          "		errorMsg+=\"  - '"
              + template.getLabel(language)
              + "' "
              + Util.getString("GML.MustBeFilled", language)
              + "\\n \";");
      out.println("		errorNb++;");
      out.println("	}");
    }

    out.println(" if (!" + template.getFieldName() + "Empty) {");
    out.println("var reg=new RegExp(\"^([01][0-9]|2[0-3]):([0-5][0-9])$\",\"g\");");
    out.println("if (!reg.test(field.value)) {");
    out.println(
        "		errorMsg+=\"  - '"
            + template.getLabel(language)
            + "' "
            + Util.getString("GML.MustContainsCorrectHour", language)
            + "\\n \";");
    out.println("		errorNb++;");
    out.println("}");
    out.println("}");

    Util.getJavascriptChecker(template.getFieldName(), PagesContext, out);
  }
  @Override
  public void displayScripts(
      final PrintWriter out, final FieldTemplate template, final PagesContext pageContext)
      throws IOException {
    checkFieldType(template.getTypeName(), "VideoFieldDisplayer.displayScripts");
    String language = pageContext.getLanguage();
    String fieldName = template.getFieldName();
    if (template.isMandatory() && pageContext.useMandatory()) {
      out.append("	if (isWhitespace(stripInitialWhitespace(field.value))) {\n")
          .append("		var ")
          .append(fieldName)
          .append("Value = document.getElementById('")
          .append(fieldName)
          .append(Field.FILE_PARAM_NAME_SUFFIX)
          .append("').value;\n")
          .append("   var ")
          .append(fieldName)
          .append("Operation = document.")
          .append(pageContext.getFormName())
          .append(".")
          .append(fieldName)
          .append(OPERATION_KEY)
          .append(".value;\n")
          .append("		if (")
          .append(fieldName)
          .append("Value=='' || ")
          .append(fieldName)
          .append("Operation=='")
          .append(Operation.DELETION.name())
          .append("') {\n")
          .append("			errorMsg+=\"  - '")
          .append(EncodeHelper.javaStringToJsString(template.getLabel(language)))
          .append("' ")
          .append(Util.getString("GML.MustBeFilled", language))
          .append("\\n \";\n")
          .append("			errorNb++;\n")
          .append("		}\n")
          .append("	}\n");
    }

    Util.includeFileNameLengthChecker(template, pageContext, out);
    Util.getJavascriptChecker(template.getFieldName(), pageContext, out);
  }
  @Override
  public boolean isEmpty(List<FileItem> items, DataRecord record, PagesContext pagesContext) {
    boolean isEmpty = true;
    Iterator<FieldTemplate> itFields = null;
    if (fieldTemplates != null) {
      itFields = this.fieldTemplates.iterator();
    }
    if (itFields != null && itFields.hasNext()) {
      FieldDisplayer fieldDisplayer = null;
      FieldTemplate fieldTemplate = null;
      while (itFields.hasNext() || !isEmpty) {
        fieldTemplate = itFields.next();
        if (fieldTemplate != null) {
          String fieldType = fieldTemplate.getTypeName();
          String fieldDisplayerName = fieldTemplate.getDisplayerName();
          try {
            if (!StringUtil.isDefined(fieldDisplayerName)) {
              fieldDisplayerName = getTypeManager().getDisplayerName(fieldType);
            }
            fieldDisplayer = getTypeManager().getDisplayer(fieldType, fieldDisplayerName);
            if (fieldDisplayer != null) {
              String itemName = fieldTemplate.getFieldName();
              String itemValue = null;

              if (Field.TYPE_FILE.equals(fieldType)) {
                FileItem image = getParameter(items, itemName);
                if (image != null
                    && !image.isFormField()
                    && StringUtil.isDefined(image.getName())) {
                  isEmpty = false;
                }
              } else {
                if (fieldDisplayerName.equals("checkbox")) {
                  itemValue = getParameterValues(items, itemName);
                } else {
                  itemValue = getParameterValue(items, itemName);
                }
                if (StringUtil.isDefined(itemValue)) {
                  isEmpty = false;
                }
              }
            }
          } catch (FormException fe) {
            SilverTrace.error("form", "XmlSearchForm.isEmpty", "form.EXP_UNKNOWN_FIELD", null, fe);
          } catch (Exception e) {
            SilverTrace.error("form", "XmlSearchForm.isEmpty", "form.EXP_UNKNOWN_FIELD", null, e);
          }
        }
      }
    }
    return isEmpty;
  }
  /**
   * Prints the HTML layout of the dataRecord using the RecordTemplate to extract labels and extra
   * informations. The value formats may be adapted to a local language. Never throws an Exception
   * but log a silvertrace and writes an empty string when :
   *
   * <UL>
   *   <LI>a field is unknown by the template.
   *   <LI>a field has not the required type.
   * </UL>
   *
   * @param pagesContext
   * @param record
   * @return
   */
  @Override
  public String toString(PagesContext pagesContext, DataRecord record) {
    SilverTrace.info("form", "XmlSearchForm.toString", "root.MSG_GEN_ENTER_METHOD");
    StringWriter sw = new StringWriter();
    String language = pagesContext.getLanguage();
    PrintWriter out = new PrintWriter(sw, true);

    if (pagesContext.getPrintTitle() && title != null && title.length() > 0) {
      out.println("<table CELLPADDING=0 CELLSPACING=2 BORDER=0 WIDTH=\"98%\" CLASS=intfdcolor>");
      out.println("<tr>");
      out.println("<td CLASS=intfdcolor4 NOWRAP>");
      out.println("<table CELLPADDING=0 CELLSPACING=0 BORDER=0 WIDTH=\"100%\">");
      out.println("<tr>");
      out.println("<td class=\"intfdcolor\" nowrap width=\"100%\">");
      out.println(
          "<img border=\"0\" src=\""
              + Util.getIcon("px")
              + "\" width=5><span class=txtNav>"
              + title
              + "</span>");
      out.println("</td>");
      out.println("</tr>");
      out.println("</table>");
      out.println("</td>");
      out.println("</tr>");
      out.println("</table>");
    }
    if (fieldTemplates != null && !fieldTemplates.isEmpty()) {
      Iterator<FieldTemplate> itFields = this.fieldTemplates.iterator();
      if (pagesContext.isBorderPrinted()) {
        out.println(
            "<table width=\"98%\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" class=intfdcolor4>");
        out.println("<tr>");
        out.println("<td nowrap>");
        out.println(
            "<table border=\"0\" cellspacing=\"0\" cellpadding=\"5\" class=\"contourintfdcolor\" width=\"100%\">");
      } else {
        out.println("<table width=\"98%\" border=\"0\" cellspacing=\"0\" cellpadding=\"5\">");
      }
      out.print("<input TYPE=\"hidden\" NAME=id VALUE=\"");
      out.print(record.getId());
      out.println("\">");
      PagesContext pc = new PagesContext(pagesContext);
      pc.setNbFields(fieldTemplates.size());
      pc.incCurrentFieldIndex(1);

      // calcul lastFieldIndex
      int lastFieldIndex = -1;
      lastFieldIndex += Integer.parseInt(pc.getCurrentFieldIndex());
      FieldDisplayer fieldDisplayer = null;

      while (itFields.hasNext()) {
        FieldTemplate fieldTemplate = itFields.next();
        if (fieldTemplate != null) {
          String fieldType = fieldTemplate.getTypeName();
          String fieldDisplayerName = fieldTemplate.getDisplayerName();
          try {
            if (!StringUtil.isDefined(fieldDisplayerName)) {
              fieldDisplayerName = getTypeManager().getDisplayerName(fieldType);
            }

            fieldDisplayer = getTypeManager().getDisplayer(fieldType, fieldDisplayerName);
            if (fieldDisplayer != null) {
              lastFieldIndex += fieldDisplayer.getNbHtmlObjectsDisplayed(fieldTemplate, pc);
            }
          } catch (FormException fe) {
            SilverTrace.error(
                "form", "XmlSearchForm.toString", "form.EXP_UNKNOWN_DISPLAYER", null, fe);
          }
        }
      }
      pc.setLastFieldIndex(lastFieldIndex);

      itFields = this.fieldTemplates.iterator();
      while (itFields.hasNext()) {
        FieldTemplate fieldTemplate = itFields.next();
        if (fieldTemplate != null) {
          String fieldName = fieldTemplate.getFieldName();
          String fieldLabel = fieldTemplate.getLabel(language);
          String fieldType = fieldTemplate.getTypeName();
          String fieldDisplayerName = fieldTemplate.getDisplayerName();
          try {
            if (!StringUtil.isDefined(fieldDisplayerName)) {
              fieldDisplayerName = getTypeManager().getDisplayerName(fieldType);
            }

            fieldDisplayer = getTypeManager().getDisplayer(fieldType, fieldDisplayerName);
          } catch (FormException fe) {
            SilverTrace.error(
                "form", "XmlSearchForm.toString", "form.EXP_UNKNOWN_DISPLAYER", null, fe);
          }
          if (fieldDisplayer != null) {
            out.println("<tr align=center>");
            if (StringUtil.isDefined(fieldLabel)) {
              out.println("<td class=\"txtlibform\" align=left width=\"200\">");
              out.println(fieldLabel);
              out.println("</td>");
            }
            out.println("<td valign=\"baseline\" align=left>");
            try {
              fieldDisplayer.display(out, record.getField(fieldName), fieldTemplate, pc);
            } catch (FormException fe) {
              SilverTrace.error(
                  "form", "XmlSearchForm.toString", "form.EX_CANT_GET_FORM", null, fe);
            }
            out.println("</td>");
            out.println("</tr>");
            ;
            pc.incCurrentFieldIndex(fieldDisplayer.getNbHtmlObjectsDisplayed(fieldTemplate, pc));
          }
        }
      }
      if (pagesContext.isBorderPrinted()) {
        out.println("</TABLE>");
        out.println("</TD>");
        out.println("</TR>");
      }
      out.println("</TABLE>");
    }
    return sw.getBuffer().toString();
  }
  /**
   * Prints the HTML value of the field. The displayed value must be updatable by the end user. The
   * value format may be adapted to a local language. The fieldName must be used to name the html
   * form input. Never throws an Exception but log a silvertrace and writes an empty string when :
   *
   * <UL>
   *   <LI>the field type is not a managed type.
   * </UL>
   *
   * @param out
   * @param field
   * @param template
   * @param pageContext
   * @throws FormException
   */
  @Override
  public void display(
      PrintWriter out, TextField field, FieldTemplate template, PagesContext pageContext)
      throws FormException {
    String value = "";
    String html = "";

    String fieldName = template.getFieldName();
    SilverTrace.info(
        "form", "TimeFieldDisplayer.display", "root.MSG_GEN_PARAM_VALUE", "fieldName=" + fieldName);
    Map<String, String> parameters = template.getParameters(pageContext.getLanguage());
    if (field == null) {
      return;
    }
    if (!field.getTypeName().equals(TextField.TYPE)) {
      SilverTrace.info(
          "form", "TimeFieldDisplayer.display", "form.INFO_NOT_CORRECT_TYPE", TextField.TYPE);
    }

    String defaultParam = (parameters.containsKey("default") ? parameters.get("default") : "");
    String defaultValue = "";
    if ("now".equalsIgnoreCase(defaultParam) && !pageContext.isIgnoreDefaultValues()) {
      defaultValue = DateUtil.formatTime(new Date());
    }
    value = (!field.isNull() ? field.getValue(pageContext.getLanguage()) : defaultValue);
    if (pageContext.isBlankFieldsUse()) {
      value = "";
    }

    if (template.isReadOnly() && !template.isHidden()) {
      html = value;
    } else {
      input inputField = new input();
      inputField.setName(template.getFieldName());
      inputField.setID(template.getFieldName());
      inputField.setValue(EncodeHelper.javaStringToHtmlString(value));
      inputField.setType(template.isHidden() ? input.hidden : input.text);
      inputField.setMaxlength("5");
      inputField.setSize("10");
      if (template.isDisabled()) {
        inputField.setDisabled(true);
      } else if (template.isReadOnly()) {
        inputField.setReadOnly(true);
      }

      img image = null;
      if (template.isMandatory()
          && !template.isDisabled()
          && !template.isReadOnly()
          && !template.isHidden()
          && pageContext.useMandatory()) {
        image = new img();
        image.setSrc(Util.getIcon("mandatoryField"));
        image.setWidth(5);
        image.setHeight(5);
        image.setBorder(0);
      }

      // print field
      if (image != null) {
        ElementContainer container = new ElementContainer();
        container.addElement(inputField);
        container.addElement("&nbsp;");
        container.addElement(image);
        out.println(container.toString());
      } else {
        out.println(inputField.toString());
      }
    }
    out.println(html);
  }
  /**
   * Displays the form part corresponding to the video input. The form input is a way to change or
   * to remove the video file if this one exists.
   *
   * @param attachmentId the identifier of the attached file containing the video to display.
   * @param template the template of the field to which is mapped the video.
   * @param pagesContext the context of the displaying page.
   */
  private void displayVideoFormInput(
      final String attachmentId,
      final FieldTemplate template,
      final ElementContainer xhtmlContainer,
      final PagesContext pagesContext) {
    String fieldName = template.getFieldName();
    String language = pagesContext.getLanguage();
    String deletionIcon = Util.getIcon("delete");
    String deletionLab = Util.getString("removeFile", language);
    String videoURL = computeVideoURL(attachmentId, pagesContext);
    Operation defaultOperation = Operation.ADD;

    if (!videoURL.isEmpty()) {
      defaultOperation = Operation.UPDATE;
      Map<String, String> parameters = template.getParameters(pagesContext.getLanguage());
      parameters.remove(PARAMETER_WIDTH);
      parameters.remove(PARAMETER_HEIGHT);
      // a link to the video
      Element videoLink = createVideoLink(videoURL, parameters);

      // a link to the deletion operation
      img deletionImage = new img();
      deletionImage
          .setAlt(deletionLab)
          .setSrc(deletionIcon)
          .setWidth(15)
          .setHeight(15)
          .setAlt(deletionLab)
          .setTitle(deletionLab);
      a removeLink = new a();
      removeLink
          .setHref("#")
          .addElement(deletionImage)
          .setOnClick(
              "javascript: document.getElementById('"
                  + fieldName
                  + "Video').style.display='none'; document."
                  + pagesContext.getFormName()
                  + "."
                  + fieldName
                  + OPERATION_KEY
                  + ".value='"
                  + Operation.DELETION.name()
                  + "';");
      div videoDiv = new div();
      videoDiv.setID(fieldName + "Video");
      videoDiv.setClass("video");
      videoDiv.addElement(videoLink);
      videoDiv.addElement("&nbsp;");
      videoDiv.addElement(removeLink);

      xhtmlContainer.addElement(videoDiv);
    }

    // the input from which a video file can be selected
    input fileInput = new input();
    fileInput.setID(fieldName);
    fileInput.setType("file");
    fileInput.setSize(50);
    fileInput.setName(fieldName);
    input attachmentInput = new input();
    attachmentInput
        .setType("hidden")
        .setName(fieldName + Field.FILE_PARAM_NAME_SUFFIX)
        .setValue(attachmentId)
        .setID(fieldName + Field.FILE_PARAM_NAME_SUFFIX);
    input operationInput = new input();
    operationInput
        .setType("hidden")
        .setName(fieldName + OPERATION_KEY)
        .setValue(defaultOperation.name())
        .setID(fieldName + OPERATION_KEY);
    div selectionDiv = new div();
    selectionDiv.setID(fieldName + "Selection");
    selectionDiv.addElement(fileInput);
    selectionDiv.addElement(attachmentInput);
    selectionDiv.addElement(operationInput);
    if (template.isMandatory() && pagesContext.useMandatory()) {
      selectionDiv.addElement(Util.getMandatorySnippet());
    }
    xhtmlContainer.addElement(selectionDiv);

    Element player =
        createVideoPlayer(videoURL, template.getParameters(pagesContext.getLanguage()));
    xhtmlContainer.addElement(player);
  }