@Override
  public FormChangeResponse doProcess(FormChangeResponse response) {

    try {
      Form form = context.getForm();
      if (form == null) {
        // TODO evaluate if this control should be removed
        log.warn(
            "Form object is not present in current FormProcessingContext, formula evaluation will be canceled. context: "
                + context);
        return response;
      }

      // Current forms implementation supports more than one object, so the loaded objects is not
      // loaded
      // at this moment any more.
      // TODO change the evaluateFormulaForField signature to remove this parameter
      Object loadedObject = null;

      FormStatusData statusData = formProcessor.read(form, context.getNamespace());

      Collection fieldNames = getEvaluableFields();
      evaluatedFields.clear();
      for (Iterator iterator = fieldNames.iterator(); iterator.hasNext(); ) {
        String fieldName = (String) iterator.next();
        Field field = form.getField(fieldName);
        evaluateFormulaForField(
            form, context.getNamespace(), field, loadedObject, statusData, response, new Date());
      }
    } catch (Exception e) {
      log.error("Error: ", e);
    }

    return null;
  }
  public void renderPendingFields() throws Exception {
    WysiwygFormEditor wysiwygFormEditor = WysiwygFormEditor.lookup();
    Form form = wysiwygFormEditor.getCurrentForm();
    Set<DataHolder> holders = form.getHolders();

    renderFragment("outputStart");

    for (DataHolder dataHolder : holders) {
      Set<DataFieldHolder> dataFieldHolders = getUnBindedFields(form, dataHolder);

      if (dataFieldHolders != null && !dataFieldHolders.isEmpty()) {
        if (dataHolder.canHaveChildren()) {
          setAttribute("id", dataHolder.getUniqeId());
          setAttribute("type", dataHolder.getTypeCode());
          setAttribute("renderColor", dataHolder.getRenderColor());

          if (dataHolder.getUniqeId() != null
              && dataHolder.getUniqeId().equals(wysiwygFormEditor.getLastDataHolderUsedId())) {
            setAttribute("open", Boolean.TRUE);
          } else {
            setAttribute("open", Boolean.FALSE);
          }
          String holderName = "";

          holderName = dataHolder.getUniqeId();
          if (holderName.length() > 20) holderName = holderName.substring(0, 19) + "...";

          setAttribute("showHolderName", holderName);
          renderFragment("outputBinding");
        }

        for (DataFieldHolder dataFieldHolder : dataFieldHolders) {
          String fieldName = dataFieldHolder.getId();
          if (fieldName != null && !form.isFieldBinded(dataHolder, fieldName)) {
            renderAddField(fieldName, dataFieldHolder, dataHolder);
          }
        }

        if (dataHolder.canHaveChildren()) {
          renderFragment("outputEndBinding");
        }
      }
    }

    renderFragment("outputEnd");
  }
  protected Set<DataFieldHolder> getUnBindedFields(Form form, DataHolder dataHolder) {
    Set<DataFieldHolder> dataFieldHolders = dataHolder.getFieldHolders();

    Set<DataFieldHolder> result = new TreeSet<DataFieldHolder>();

    if (dataFieldHolders == null || dataFieldHolders.isEmpty()) return result;

    for (DataFieldHolder dataFieldHolder : dataFieldHolders) {
      String fieldName = dataFieldHolder.getId();
      if (fieldName != null && !form.isFieldBinded(dataHolder, fieldName)) {
        result.add(dataFieldHolder);
      }
    }

    return result;
  }
 protected void evaluateFormulaForField(
     Form form,
     String namespace,
     Field field,
     Object loadedObject,
     FormStatusData statusData,
     FormChangeResponse response,
     Date date) {
   evaluatedFields.add(field.getFieldName());
   String defaultFormula = field.getDefaultValueFormula();
   if (defaultFormula != null && defaultFormula.startsWith("=")) {
     Object value =
         evaluateFormula(
             form,
             namespace,
             defaultFormula.substring(1),
             loadedObject,
             statusData,
             response,
             field,
             date);
     FormStatusData status1 = formProcessor.read(form, namespace);
     Object currentFieldValue = status1.getCurrentValue(field.getFieldName());
     if ((currentFieldValue != null && value == null)
         || (value != null && !value.equals(currentFieldValue))) {
       FieldHandler fieldHandler = fieldHandlersManager.getHandler(field.getFieldType());
       Map fieldValuesMap =
           fieldHandler.getParamValue(
               namespace
                   + FormProcessor.NAMESPACE_SEPARATOR
                   + form.getId()
                   + FormProcessor.NAMESPACE_SEPARATOR
                   + field.getFieldName(),
               value,
               field.getFieldPattern());
       formProcessor.setValues(form, namespace, fieldValuesMap, fieldValuesMap, true);
     }
   }
 }
  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;
  }
  /**
   * 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 Form deserializeForm(Node nodeForm, String path, Map<String, Properties> resources)
      throws Exception {
    if (!nodeForm.getNodeName().equals(NODE_FORM)) return null;

    Form form = formManager.createForm("");
    form.setId(
        Long.valueOf(
            StringEscapeUtils.unescapeXml(
                nodeForm.getAttributes().getNamedItem(ATTR_ID).getNodeValue())));

    Set<Field> fields = new TreeSet<Field>();
    NodeList childNodes = nodeForm.getChildNodes();
    for (int i = 0; i < childNodes.getLength(); i++) {
      Node node = childNodes.item(i);
      if (node.getNodeName().equals(NODE_PROPERTY)) {
        String propName = node.getAttributes().getNamedItem(ATTR_NAME).getNodeValue();
        String value =
            StringEscapeUtils.unescapeXml(
                node.getAttributes().getNamedItem(ATTR_VALUE).getNodeValue());
        if ("subject".equals(propName)) {
          form.setSubject(value);
        } else if ("name".equals(propName)) {
          form.setName(value);
        } else if ("displayMode".equals(propName)) {
          form.setDisplayMode(value);
        } else if ("labelMode".equals(propName)) {
          form.setLabelMode(value);
        } else if ("showMode".equals(propName)) {
          form.setShowMode(value);
        } else if ("status".equals(propName)) {
          form.setStatus(Long.valueOf(value));
        } else if ("formTemplate".equals(propName)) {
          form.setFormTemplate(value);
        }
      } else if (node.getNodeName().equals(NODE_FIELD)) {
        Field field = deserializeField(form, node, resources);
        field.setForm(form);
        fields.add(field);
      } else if (node.getNodeName().equals(NODE_DATA_HOLDER)) {
        String holderId = getNodeAttributeValue(node, ATTR_ID);
        String holderInputId = getNodeAttributeValue(node, ATTR_INPUT_ID);
        String holderOutId = getNodeAttributeValue(node, ATTR_OUT_ID);
        String holderType = getNodeAttributeValue(node, ATTR_TYPE);
        String holderValue = getNodeAttributeValue(node, ATTR_VALUE);
        String holderRenderColor = getNodeAttributeValue(node, ATTR_NAME);
        String holderSupportedType = getNodeAttributeValue(node, ATTR_SUPPORTED_TYPE);

        if (!StringUtils.isEmpty(holderId)
            && !StringUtils.isEmpty(holderType)
            && !StringUtils.isEmpty(holderValue)) {

          DataHolderBuildConfig config =
              new DataHolderBuildConfig(
                  holderId, holderInputId, holderOutId, holderRenderColor, holderValue);
          config.addAttribute("path", path);
          if (!StringUtils.isEmpty(holderSupportedType))
            config.addAttribute(ATTR_SUPPORTED_TYPE, holderSupportedType);

          DataHolder holder = dataHolderManager.createDataHolderByType(holderType, config);

          if (!StringUtils.isEmpty(holderId)) form.setDataHolder(holder);
        }
      }
    }
    if (fields != null) form.setFormFields(fields);
    return form;
  }
  public void renderDataHolders() {
    try {
      renderFragment("outputStartHeader");
      for (DataHolderBuilder builder : dataHolderManager.getHolderBuilders()) {

        if (builder instanceof RangedDataHolderBuilder)
          notifyHolderBuilder(
              (RangedDataHolderBuilder) builder,
              wysiwygFormEditor.getCurrentEditionContext().getPath());
        else notifyHolderBuilder(builder);
      }
      renderFragment("outputEndHeader");

      renderFragment("outputStart");

      Form form = wysiwygFormEditor.getCurrentForm();
      Set<DataHolder> holders = form.getHolders();
      String existingIds = "\"\"";
      String existingInputIds = "\"\"";
      String existingOutputIds = "\"\"";
      for (DataHolder holder : holders) {
        if (!StringUtils.isEmpty(holder.getInputId()))
          existingInputIds += ", \"" + holder.getInputId() + "\" ";
        if (!StringUtils.isEmpty(holder.getOuputId()))
          existingOutputIds += ", \"" + holder.getOuputId() + "\" ";
        if (!StringUtils.isEmpty(holder.getUniqeId()))
          existingIds += ", \"" + holder.getUniqeId() + "\" ";
      }

      setAttribute("existingIds", existingIds);
      setAttribute("existingInputIds", existingInputIds);
      setAttribute("existingOutputIds", existingOutputIds);
      renderFragment("outputFormAddHolderStart");

      Map<String, String> colors = dataHolderManager.getHolderColors();

      for (Iterator it = colors.keySet().iterator(); it.hasNext(); ) {
        String color = (String) it.next();
        String name = colors.get(color);
        setAttribute("color", color);
        setAttribute("name", name);
        renderFragment("color");
      }

      Map<String, String> builderNames = new HashMap<String, String>();

      // Render source types sorted by value.
      renderFragment("outputFormHolderTypes");

      for (DataHolderBuilder builder : dataHolderManager.getHolderBuilders()) {
        String holderName = builder.getDataHolderName(getLocale());
        builderNames.put(builder.getId(), holderName);
        setAttribute("holderType", builder.getId());
        setAttribute("holderName", holderName);
        renderFragment("outputHolderType");
      }

      renderFragment("outputEndHolderTypes");

      renderFragment("outputStartBindings");

      int i = 0;
      for (DataHolder holder : holders) {
        setAttribute("id", StringUtils.defaultString(holder.getUniqeId()));
        setAttribute("input_id", StringUtils.defaultString(holder.getInputId()));
        setAttribute("outId", StringUtils.defaultString(holder.getOuputId()));
        setAttribute("deleteId", StringUtils.defaultString(holder.getUniqeId()));
        setAttribute(
            "type",
            builderNames.get(
                StringUtils.defaultIfEmpty(holder.getSupportedType(), holder.getTypeCode())));
        setAttribute("renderColor", holder.getRenderColor());
        setAttribute("value", holder.getInfo());
        setAttribute("rowStyle", i % 2 == 1 ? "skn-even_row" : "skn-odd_row");
        i++;
        renderFragment("outputBindings");
      }
      renderFragment("outputEndBindings");

      renderFragment("outputEnd");
    } catch (Exception e) {
      log.error("Error:", e);
    }
  }