/**
   * Generates the xml representation and mount in rootNode the structure to be included. Fills the
   * XMLNode structure with the form representation and returns the string.
   */
  public String generateFormXML(Form form, XMLNode rootNode) throws Exception {
    rootNode.addAttribute(ATTR_ID, form.getId().toString());

    addXMLNode("subject", form.getSubject(), rootNode);
    addXMLNode("name", form.getName(), rootNode);
    addXMLNode("displayMode", form.getDisplayMode(), rootNode);
    addXMLNode("labelMode", form.getLabelMode(), rootNode);
    addXMLNode("showMode", form.getShowMode(), rootNode);
    addXMLNode(
        "status", (form.getStatus() != null ? String.valueOf(form.getStatus()) : null), rootNode);
    addXMLNode("formTemplate", form.getFormTemplate(), rootNode);

    for (Field field : form.getFormFields()) {
      generateFieldXML(field, rootNode);
    }

    for (DataHolder dataHolder : form.getHolders()) {
      generateDataHolderXML(dataHolder, rootNode);
    }

    StringWriter sw = new StringWriter();
    rootNode.writeXML(sw, true);

    return sw.toString();
  }
  public Field deserializeField(Form form, Node nodeField, Map<String, Properties> resources)
      throws Exception {
    if (!nodeField.getNodeName().equals(NODE_FIELD)) return null;

    Field field = new Field();
    field.setId(Long.valueOf(nodeField.getAttributes().getNamedItem(ATTR_ID).getNodeValue()));
    field.setFieldName(nodeField.getAttributes().getNamedItem(ATTR_NAME).getNodeValue());
    field.setPosition(
        Integer.parseInt(nodeField.getAttributes().getNamedItem(ATTR_POSITION).getNodeValue()));
    field.setFieldType(
        fieldTypeManager.getTypeByCode(
            nodeField.getAttributes().getNamedItem(ATTR_TYPE).getNodeValue()));

    Node bag = nodeField.getAttributes().getNamedItem(ATTR_BAG_TYPE);

    if (bag != null) {
      field.setBag(bag.getNodeValue());
    }

    NodeList fieldPropsNodes = nodeField.getChildNodes();
    for (int j = 0; j < fieldPropsNodes.getLength(); j++) {
      Node nodeFieldProp = fieldPropsNodes.item(j);
      if (nodeFieldProp.getNodeName().equals(NODE_PROPERTY)) {
        String propName = nodeFieldProp.getAttributes().getNamedItem(ATTR_NAME).getNodeValue();
        String value =
            StringEscapeUtils.unescapeXml(
                nodeFieldProp.getAttributes().getNamedItem(ATTR_VALUE).getNodeValue());
        if (propName != null && value != null) {
          if ("fieldRequired".equals(propName)) {
            field.setFieldRequired(Boolean.valueOf(value));
          } else if ("groupWithPrevious".equals(propName)) {
            field.setGroupWithPrevious(Boolean.valueOf(value));
          } else if ("height".equals(propName)) {
            field.setHeight(value);
          } else if ("labelCSSClass".equals(propName)) {
            field.setLabelCSSClass(value);
          } else if ("labelCSSStyle".equals(propName)) {
            field.setLabelCSSStyle(value);
          } else if ("label".equals(propName)) {
            field.setLabel(deserializeI18nEntrySet(value));
          } else if ("errorMessage".equals(propName)) {
            field.setErrorMessage(deserializeI18nEntrySet(value));
          } else if ("title".equals(propName)) {
            field.setTitle(deserializeI18nEntrySet(value));
          } else if ("readonly".equals(propName)) {
            field.setReadonly(Boolean.valueOf(value));
          } else if ("size".equals(propName)) {
            if (!StringUtils.isEmpty(value) && StringUtils.isNumeric(value))
              field.setSize(Long.valueOf(value));
          } else if ("formula".equals(propName)) {
            field.setFormula(value);
          } else if ("rangeFormula".equals(propName)) {
            field.setRangeFormula(value);
          } else if ("pattern".equals(propName)) {
            field.setPattern(value);
          } else if ("maxlength".equals(propName)) {
            if (!StringUtils.isEmpty(value) && StringUtils.isNumeric(value))
              field.setMaxlength(Long.valueOf(value));
          } else if ("styleclass".equals(propName)) {
            field.setStyleclass(value);
          } else if ("cssStyle".equals(propName)) {
            field.setCssStyle(value);
          } else if ("tabindex".equals(propName)) {
            if (!StringUtils.isEmpty(value) && StringUtils.isNumeric(value))
              field.setTabindex(Long.valueOf(value));
          } else if ("accesskey".equals(propName)) {
            field.setAccesskey(value);
          } else if ("isHTML".equals(propName)) {
            field.setIsHTML(Boolean.valueOf(value));
          } else if ("htmlContent".equals(propName)) {
            field.setHtmlContent(deserializeHMLI18nEntrySet(value));
          } else if ("hideContent".equals(propName)) {
            field.setHideContent(Boolean.valueOf(value));
          } else if ("defaultValueFormula".equals(propName)) {
            field.setDefaultValueFormula(value);
          } else if ("defaultSubform".equals(propName)) {
            field.setDefaultSubform(value);
          } else if ("previewSubform".equals(propName)) {
            field.setPreviewSubform(value);
          } else if ("tableSubform".equals(propName)) {
            field.setTableSubform(value);
          } else if ("newItemText".equals(propName)) {
            field.setNewItemText(deserializeI18nEntrySet(value));
          } else if ("addItemText".equals(propName)) {
            field.setAddItemText(deserializeI18nEntrySet(value));
          } else if ("cancelItemText".equals(propName)) {
            field.setCancelItemText(deserializeI18nEntrySet(value));
          } else if ("deleteItems".equals(propName)) {
            field.setDeleteItems(Boolean.valueOf(value));
          } else if ("updateItems".equals(propName)) {
            field.setUpdateItems(Boolean.valueOf(value));
          } else if ("visualizeItems".equals(propName)) {
            field.setVisualizeItem(Boolean.valueOf(value));
          } else if ("hideCreateItem".equals(propName)) {
            field.setHideCreateItem(Boolean.valueOf(value));
          } else if ("expanded".equals(propName)) {
            field.setExpanded(Boolean.valueOf(value));
          } else if ("enableTableEnterData".equals(propName)) {
            field.setEnableTableEnterData(Boolean.valueOf(value));
          } else if ("inputBinding".equals(propName)) {
            field.setInputBinding(value);
          } else if ("outputBinding".equals(propName)) {
            field.setOutputBinding(value);
          } else if ("customFieldType".equals(propName)) {
            field.setCustomFieldType(value);
          } else if ("param1".equals(propName)) {
            field.setParam1(value);
          } else if ("param2".equals(propName)) {
            field.setParam2(value);
          } else if ("param3".equals(propName)) {
            field.setParam3(value);
          } else if ("param4".equals(propName)) {
            field.setParam4(value);
          } else if ("param5".equals(propName)) {
            field.setParam5(value);
          } else if ("fieldClass".equals(propName)) {
            field.getFieldType().setFieldClass(value);
          } else if ("onChangeScript".equals(propName)) {
            field.setOnChangeScript(value);
          }
        }
      }
    }

    if (resources != null) {
      field.setTitle(new I18nSet());
      field.setLabel(new I18nSet());
      field.setErrorMessage(new I18nSet());
      if (resources.containsKey("default")) {
        resources.put(localeManager.getDefaultLang(), resources.remove("default"));
      }
      for (String lang : resources.keySet()) {
        Properties props = resources.get(lang);
        String value = getFieldProperty(form.getName(), field.getFieldName(), "title", props);
        if (!StringUtils.isEmpty(value)) field.getTitle().setValue(lang, value);

        value = getFieldProperty(form.getName(), field.getFieldName(), "label", props);
        if (!StringUtils.isEmpty(value)) field.getLabel().setValue(lang, value);

        value = getFieldProperty(form.getName(), field.getFieldName(), "errorMessage", props);
        if (!StringUtils.isEmpty(value)) field.getErrorMessage().setValue(lang, value);
      }
    }
    return field;
  }