This is an automated email from the ASF dual-hosted git repository.
mridulpathak pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/trunk by this push:
new ab38bcdd65 Improved: MacroFormRenderer builds the form structure and
hyperlink macro calls with RenderableFtlFormElementsBuilder (OFBIZ-13680)
ab38bcdd65 is described below
commit ab38bcdd65e6f830f89a4c0974a109e98ff817ca
Author: Mridul Pathak <[email protected]>
AuthorDate: Fri Oct 16 13:31:35 2026 +0530
Improved: MacroFormRenderer builds the form structure and hyperlink macro
calls with RenderableFtlFormElementsBuilder (OFBIZ-13680)
MacroFormRenderer built the macro calls of the form structure (form, list
and row wrappers, header, cell and field row macros, boundary comments) and of
the hyperlinks as text and compiled them. RenderableFtlFormElementsBuilder now
creates these macro calls, so that FtlWriter passes their values as data, and
the hand-built copy of the hyperlink code in MacroFormRenderer is replaced by
the one that the builder already had, which now gives the same output. The
macro signatures and the o [...]
- the parameters of a layered modal link are passed as the JSON string that
the macro expects, with the presentation layer, instead of as a map, and the
text of the link is passed as well.
- the form of a hidden form link in a multi form is written after the
closing of the multi form, which never happened for the sub hyperlinks of the
display entity and text fields.
- FtlWriter writes a RenderableFtlString as it is instead of compiling it
as a template, so that an interpolation in the description of a hidden form
link is not evaluated.
- the description of a hidden form link with a quote does not show a
backslash before the quote anymore.
---
.../ofbiz/widget/renderer/macro/FtlWriter.java | 11 +-
.../widget/renderer/macro/MacroFormRenderer.java | 575 ++-------------------
.../macro/RenderableFtlFormElementsBuilder.java | 345 ++++++++++++-
.../macro/renderable/RenderableFtlString.java | 4 +
.../ofbiz/widget/renderer/macro/FtlWriterTest.java | 75 +++
.../renderer/macro/MacroFormRendererTest.java | 203 ++++----
.../RenderableFtlFormElementsBuilderTest.java | 346 +++++++++++++
7 files changed, 910 insertions(+), 649 deletions(-)
diff --git
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/FtlWriter.java
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/FtlWriter.java
index c7e9ed3dc9..8261efbd8b 100644
---
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/FtlWriter.java
+++
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/FtlWriter.java
@@ -172,8 +172,8 @@ public final class FtlWriter {
}
/**
- * Visitor for RenderableFtl objects that will process the contents of the
objects as FTL templates and write the
- * results to the configured Appendable.
+ * Visitor for RenderableFtl objects that will call the macros of the
macro library, or write the finished output
+ * of a RenderableFtlString as it is, to the configured Appendable.
*/
private final class RenderableFtlFtlWriterVisitor implements
RenderableFtlVisitor {
@@ -199,7 +199,12 @@ public final class FtlWriter {
@Override
public void visit(RenderableFtlString renderableFtlString, Locale
locale) {
- processFtlString(writer, locale,
renderableFtlString.getFtlString());
+ // the string holds finished output that can contain data, so it
is written as it is and never compiled
+ try {
+ writer.append(renderableFtlString.getFtlString());
+ } catch (IOException e) {
+ Debug.logError(e, "Error writing the output of a
RenderableFtlString", MODULE);
+ }
}
}
}
diff --git
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java
index e1cb37ba1f..c3f8144f3e 100644
---
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java
+++
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRenderer.java
@@ -21,7 +21,6 @@ package org.apache.ofbiz.widget.renderer.macro;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
-import java.net.URI;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
@@ -29,21 +28,17 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
-import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
-import org.apache.commons.text.StringEscapeUtils;
import org.apache.ofbiz.base.util.Debug;
-import org.apache.ofbiz.base.util.StringUtil;
import org.apache.ofbiz.base.util.UtilCodec;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.base.util.UtilHttp;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilProperties;
-import org.apache.ofbiz.base.util.UtilRandom;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.base.util.string.FlexibleStringExpander;
import org.apache.ofbiz.entity.Delegator;
@@ -53,7 +48,6 @@ import org.apache.ofbiz.webapp.taglib.ContentUrlTag;
import org.apache.ofbiz.widget.WidgetWorker;
import org.apache.ofbiz.widget.content.StaticContentUrlProvider;
import org.apache.ofbiz.widget.model.CommonWidgetModels;
-import org.apache.ofbiz.widget.model.FieldInfo;
import org.apache.ofbiz.widget.model.ModelForm;
import org.apache.ofbiz.widget.model.ModelFormField;
import org.apache.ofbiz.widget.model.ModelFormField.CheckField;
@@ -80,7 +74,6 @@ import
org.apache.ofbiz.widget.model.ModelFormField.TextFindField;
import org.apache.ofbiz.widget.model.ModelFormField.TextareaField;
import org.apache.ofbiz.widget.model.ModelScreenWidget;
import org.apache.ofbiz.widget.model.ModelSingleForm;
-import org.apache.ofbiz.widget.model.ModelTheme;
import org.apache.ofbiz.widget.model.ModelWidget;
import org.apache.ofbiz.widget.model.ThemeFactory;
import org.apache.ofbiz.widget.renderer.FormRenderer;
@@ -90,7 +83,6 @@ import org.apache.ofbiz.widget.renderer.UtilHelpText;
import org.apache.ofbiz.widget.renderer.VisualTheme;
import org.apache.ofbiz.widget.renderer.macro.renderable.RenderableFtl;
import
org.apache.ofbiz.widget.renderer.macro.renderable.RenderableFtlMacroCall;
-import org.jsoup.nodes.Element;
/**
* Widget Library - Form Renderer implementation based on Freemarker macros
@@ -228,10 +220,11 @@ public final class MacroFormRenderer implements
FormStringRenderer {
this.request.setAttribute("width", hyperlinkField.getWidth());
this.request.setAttribute("height", hyperlinkField.getHeight());
this.request.setAttribute("text", hyperlinkField.getText(context));
- makeHyperlinkByType(writer, hyperlinkField.getLinkType(),
modelFormField.getWidgetStyle(), hyperlinkField.getUrlMode(),
- hyperlinkField.getTarget(context),
hyperlinkField.getParameterMap(context, modelFormField.getEntityName(),
- modelFormField.getServiceName()),
hyperlinkField.getDescription(context), hyperlinkField.getTargetWindow(context),
- hyperlinkField.getConfirmation(context), modelFormField,
this.request, this.response, context);
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.makeHyperlinkByType(hyperlinkField.getLinkType(),
+ modelFormField.getWidgetStyle(), hyperlinkField.getUrlMode(),
hyperlinkField.getTarget(context),
+ hyperlinkField.getParameterMap(context,
modelFormField.getEntityName(), modelFormField.getServiceName()),
+ hyperlinkField.getDescription(context),
hyperlinkField.getTargetWindow(context),
+ hyperlinkField.getConfirmation(context), modelFormField,
this.request, this.response, context));
this.appendTooltip(writer, context, modelFormField);
this.request.removeAttribute("image");
this.request.removeAttribute("descriptionSize");
@@ -345,7 +338,6 @@ public final class MacroFormRenderer implements
FormStringRenderer {
} else {
titleText = UtilHttp.encodeAmpersands(titleText);
final String encodedTitleText = encodeForMacro(titleText,
modelFormField, context);
- titleText = encode(titleText, modelFormField, context);
if (UtilValidate.isNotEmpty(modelFormField.getHeaderLink())) {
StringBuilder targetBuffer = new StringBuilder();
FlexibleStringExpander target =
FlexibleStringExpander.getInstance(modelFormField.getHeaderLink());
@@ -357,8 +349,8 @@ public final class MacroFormRenderer implements
FormStringRenderer {
targetType = "plain";
}
StringWriter sr = new StringWriter();
- makeHyperlinkString(sr,
modelFormField.getHeaderLinkStyle(), targetType, targetBuffer.toString(), null,
titleText, "",
- modelFormField, this.request, this.response,
context, "");
+ writeFtlElement(sr,
renderableFtlFormElementsBuilder.hyperlinkMacroCall(modelFormField.getHeaderLinkStyle(),
targetType,
+ targetBuffer.toString(), null, encodedTitleText,
"", modelFormField, this.request, this.response, context, ""));
String hyperlinkTitle = sr.toString().replace("\"", "\'");
writeFtlElement(writer,
renderableFtlFormElementsBuilder.hyperlinkTitle(modelFormField.getModelForm().getName(),
hyperlinkTitle, false));
@@ -407,81 +399,12 @@ public final class MacroFormRenderer implements
FormStringRenderer {
} else {
renderBeginningBoundaryComment(writer, "Grid Widget - Grid
Element", modelForm);
}
- String targetType = modelForm.getTargetType();
- String targ = modelForm.getTarget(context, targetType);
- StringBuilder linkUrl = new StringBuilder();
- if (UtilValidate.isNotEmpty(targ)) {
- final URI linkUri = WidgetWorker.buildHyperlinkUri(targ,
targetType, null, null, false, false, true,
- request, response);
- linkUrl.append(linkUri.toString());
- }
- String formType = modelForm.getType();
- String targetWindow = modelForm.getTargetWindow(context);
- String containerId = FormRenderer.getCurrentContainerId(modelForm,
context);
- String containerStyle = modelForm.getContainerStyle();
- String autocomplete = "";
- String name = FormRenderer.getCurrentFormName(modelForm, context);
- String viewIndexField = modelForm.getMultiPaginateIndexField(context);
- String viewSizeField = modelForm.getMultiPaginateSizeField(context);
- int viewIndex = Paginator.getViewIndex(modelForm, context);
- int viewSize = Paginator.getViewSize(modelForm, context);
- boolean useRowSubmit = modelForm.getUseRowSubmit();
- if (!modelForm.getClientAutocompleteFields()) {
- autocomplete = "off";
- }
- String hasRequiredField = "";
- for (ModelFormField formField : modelForm.getFieldList()) {
- if (formField.getRequiredField()) {
- hasRequiredField = "Y";
- break;
- }
- }
- String focusFieldName = modelForm.getFocusFieldName();
-
- // Generate CSRF name & value for form
- String csrfNameValue = CsrfUtil.getTokenNameNonAjax() + " " +
CsrfUtil.generateTokenForNonAjax(request, targ);
-
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormOpen ");
- sr.append(" linkUrl=\"");
- sr.append(linkUrl);
- sr.append("\" formType=\"");
- sr.append(formType);
- sr.append("\" targetWindow=\"");
- sr.append(targetWindow);
- sr.append("\" containerId=\"");
- sr.append(containerId);
- sr.append("\" containerStyle=\"");
- sr.append(containerStyle);
- sr.append("\" autocomplete=\"");
- sr.append(autocomplete);
- sr.append("\" name=\"");
- sr.append(name);
- sr.append("\" focusFieldName=\"");
- sr.append(focusFieldName);
- sr.append("\" hasRequiredField=\"");
- sr.append(hasRequiredField);
- sr.append("\" viewIndexField=\"");
- sr.append(viewIndexField);
- sr.append("\" viewSizeField=\"");
- sr.append(viewSizeField);
- sr.append("\" viewIndex=\"");
- sr.append(Integer.toString(viewIndex));
- sr.append("\" viewSize=\"");
- sr.append(Integer.toString(viewSize));
- sr.append("\" useRowSubmit=");
- sr.append(Boolean.toString(useRowSubmit));
- sr.append(" csrfNameValue=\"");
- sr.append(csrfNameValue);
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formOpen(context, modelForm));
}
@Override
public void renderFormClose(Appendable writer, Map<String, Object>
context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormClose />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer, renderableFtlFormElementsBuilder.formClose());
if (modelForm instanceof ModelSingleForm) {
renderEndingBoundaryComment(writer, "Form Widget - Form Element",
modelForm);
} else {
@@ -509,15 +432,9 @@ public final class MacroFormRenderer implements
FormStringRenderer {
// this.renderFormatItemRowCellClose(writer, context,
modelForm, submitField);
}
}
- StringWriter sr = new StringWriter();
- sr.append("<@renderMultiFormClose />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.multiFormClose());
// see if there is anything that needs to be added outside of the
multi-form
- Map<String, Object> wholeFormContext =
UtilGenerics.cast(context.get("wholeFormContext"));
- Appendable postMultiFormWriter = wholeFormContext != null ?
(Appendable) wholeFormContext.get("postMultiFormWriter") : null;
- if (postMultiFormWriter != null) {
- writer.append(postMultiFormWriter.toString());
- }
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.postMultiFormContent(context));
if (modelForm instanceof ModelSingleForm) {
renderEndingBoundaryComment(writer, "Form Widget - Form Element",
modelForm);
} else {
@@ -546,63 +463,17 @@ public final class MacroFormRenderer implements
FormStringRenderer {
if (this.renderPagination) {
this.renderNextPrev(writer, context, modelForm);
}
- List<ModelFormField> childFieldList = modelForm.getFieldList();
- List<String> columnStyleList = new LinkedList<>();
- List<String> fieldNameList = new LinkedList<>();
- for (ModelFormField childField : childFieldList) {
- int childFieldType = childField.getFieldInfo().getFieldType();
- if (childFieldType == FieldInfo.HIDDEN || childFieldType ==
FieldInfo.IGNORED) {
- continue;
- }
- String areaStyle = childField.getTitleAreaStyle();
- if (UtilValidate.isEmpty(areaStyle)) {
- areaStyle = "";
- }
- if (fieldNameList.contains(childField.getName())) {
- if (UtilValidate.isNotEmpty(areaStyle)) {
-
columnStyleList.set(fieldNameList.indexOf(childField.getName()), areaStyle);
- }
- } else {
- columnStyleList.add(areaStyle);
- fieldNameList.add(childField.getName());
- }
- }
- String columnStyleListString =
- columnStyleList.stream().map(str -> "'" + str +
"'").collect(Collectors.joining(", "));
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatListWrapperOpen ");
- sr.append(" formName=\"");
- sr.append(modelForm.getName());
- sr.append("\" style=\"");
-
sr.append(FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(),
context));
- sr.append("\" columnStyles=[");
- if (UtilValidate.isNotEmpty(columnStyleListString)) {
- // this is a fix for forms with no fields
- sr.append(columnStyleListString);
- }
- sr.append("] />");
- executeMacro(writer, sr.toString());
-
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatListWrapperOpen(context, modelForm));
}
@Override
public void renderEmptyFormDataMessage(Appendable writer, Map<String,
Object> context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderEmptyFormDataMessage");
- sr.append(" message=\"");
- sr.append(modelForm.getEmptyFormDataMessage(context));
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.emptyFormDataMessage(context, modelForm));
}
@Override
public void renderFormatListWrapperClose(Appendable writer, Map<String,
Object> context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatListWrapperClose");
- sr.append(" formName=\"");
- sr.append(modelForm.getName());
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatListWrapperClose(modelForm));
if (this.renderPagination) {
this.renderNextPrev(writer, context, modelForm);
}
@@ -615,230 +486,112 @@ public final class MacroFormRenderer implements
FormStringRenderer {
@Override
public void renderFormatHeaderOpen(Appendable writer, Map<String, Object>
context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatHeaderOpen ");
- sr.append(" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatHeaderOpen());
}
@Override
public void renderFormatHeaderClose(Appendable writer, Map<String, Object>
context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatHeaderClose");
- sr.append(" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatHeaderClose());
}
@Override
public void renderFormatHeaderRowOpen(Appendable writer, Map<String,
Object> context, ModelForm modelForm) throws IOException {
- String headerStyle =
FlexibleStringExpander.expandString(modelForm.getHeaderRowStyle(), context);
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatHeaderRowOpen ");
- sr.append(" style=\"");
- sr.append(headerStyle);
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatHeaderRowOpen(context, modelForm));
}
@Override
public void renderFormatHeaderRowClose(Appendable writer, Map<String,
Object> context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatHeaderRowClose />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatHeaderRowClose());
}
@Override
public void renderFormatHeaderRowCellOpen(Appendable writer, Map<String,
Object> context, ModelForm modelForm, ModelFormField modelFormField,
int positionSpan) throws
IOException {
- String areaStyle = modelFormField.getTitleAreaStyle();
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatHeaderRowCellOpen ");
- sr.append(" style=\"");
- sr.append(areaStyle);
- sr.append("\" positionSpan=");
- sr.append(Integer.toString(positionSpan));
- sr.append(" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatHeaderRowCellOpen(modelFormField,
positionSpan));
}
@Override
public void renderFormatHeaderRowCellClose(Appendable writer, Map<String,
Object> context, ModelForm modelForm, ModelFormField modelFormField)
throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatHeaderRowCellClose />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatHeaderRowCellClose());
}
@Override
public void renderFormatHeaderRowFormCellOpen(Appendable writer,
Map<String, Object> context, ModelForm modelForm) throws IOException {
- String areaStyle = modelForm.getFormTitleAreaStyle();
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatHeaderRowFormCellOpen ");
- sr.append(" style=\"");
- sr.append(areaStyle);
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatHeaderRowFormCellOpen(modelForm));
}
@Override
public void renderFormatHeaderRowFormCellClose(Appendable writer,
Map<String, Object> context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatHeaderRowFormCellClose />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatHeaderRowFormCellClose());
}
@Override
public void renderFormatHeaderRowFormCellTitleSeparator(Appendable writer,
Map<String, Object> context, ModelForm modelForm,
ModelFormField
modelFormField, boolean isLast) throws IOException {
- String titleStyle = modelFormField.getTitleStyle();
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatHeaderRowFormCellTitleSeparator ");
- sr.append(" style=\"");
- sr.append(titleStyle);
- sr.append("\" isLast=");
- sr.append(Boolean.toString(isLast));
- sr.append(" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatHeaderRowFormCellTitleSeparator(modelFormField,
isLast));
}
@Override
public void renderFormatItemRowOpen(Appendable writer, Map<String, Object>
context, ModelForm modelForm) throws IOException {
- Integer itemIndex = (Integer) context.get("itemIndex");
- String altRowStyles = "";
- String evenRowStyle = "";
- String oddRowStyle = "";
- if (itemIndex != null) {
- altRowStyles = modelForm.getStyleAltRowStyle(context);
- if (itemIndex % 2 == 0) {
- evenRowStyle = modelForm.getEvenRowStyle();
- } else {
- oddRowStyle =
FlexibleStringExpander.expandString(modelForm.getOddRowStyle(), context);
- }
- }
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatItemRowOpen ");
- sr.append(" formName=\"");
- sr.append(modelForm.getName());
- sr.append("\" itemIndex=");
- sr.append(String.valueOf(itemIndex));
- sr.append(" altRowStyles=\"");
- sr.append(altRowStyles);
- sr.append("\" evenRowStyle=\"");
- sr.append(evenRowStyle);
- sr.append("\" oddRowStyle=\"");
- sr.append(oddRowStyle);
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatItemRowOpen(context, modelForm));
}
@Override
public void renderFormatItemRowClose(Appendable writer, Map<String,
Object> context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatItemRowClose ");
- sr.append(" formName=\"");
- sr.append(modelForm.getName());
- sr.append("\"/>");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatItemRowClose(modelForm));
}
@Override
public void renderFormatItemRowCellOpen(Appendable writer, Map<String,
Object> context, ModelForm modelForm, ModelFormField modelFormField,
int positionSpan) throws
IOException {
- String areaStyle = modelFormField.getWidgetAreaStyle();
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatItemRowCellOpen ");
- sr.append(" fieldName=\"");
- sr.append(modelFormField.getName());
- sr.append("\" style=\"");
- sr.append(areaStyle);
- sr.append("\" positionSpan=");
- sr.append(Integer.toString(positionSpan));
- sr.append(" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatItemRowCellOpen(modelFormField,
positionSpan));
}
@Override
public void renderFormatItemRowCellClose(Appendable writer, Map<String,
Object> context, ModelForm modelForm, ModelFormField modelFormField)
throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatItemRowCellClose");
- sr.append(" fieldName=\"");
- sr.append(modelFormField.getName());
- sr.append("\"/>");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatItemRowCellClose(modelFormField));
}
@Override
public void renderFormatItemRowFormCellOpen(Appendable writer, Map<String,
Object> context, ModelForm modelForm) throws IOException {
- String areaStyle = modelForm.getFormTitleAreaStyle();
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatItemRowFormCellOpen ");
- sr.append(" style=\"");
- sr.append(areaStyle);
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatItemRowFormCellOpen(modelForm));
}
@Override
public void renderFormatItemRowFormCellClose(Appendable writer,
Map<String, Object> context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatItemRowFormCellClose />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatItemRowFormCellClose());
}
@Override
public void renderFormatSingleWrapperOpen(Appendable writer, Map<String,
Object> context, ModelForm modelForm) throws IOException {
- String style =
FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context);
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatSingleWrapperOpen ");
- sr.append(" formName=\"");
- sr.append(modelForm.getName());
- sr.append("\" style=\"");
- sr.append(style);
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatSingleWrapperOpen(context, modelForm));
}
@Override
public void renderFormatSingleWrapperClose(Appendable writer, Map<String,
Object> context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatSingleWrapperClose");
- sr.append(" formName=\"");
- sr.append(modelForm.getName());
- sr.append("\"/>");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatSingleWrapperClose(modelForm));
}
@Override
public void renderFormatFieldRowOpen(Appendable writer, Map<String,
Object> context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatFieldRowOpen />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatFieldRowOpen());
}
@Override
public void renderFormatFieldRowClose(Appendable writer, Map<String,
Object> context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatFieldRowClose />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatFieldRowClose());
}
@Override
public void renderFormatFieldRowTitleCellOpen(Appendable writer,
Map<String, Object> context, ModelFormField modelFormField) throws IOException {
- String style = modelFormField.getTitleAreaStyle();
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatFieldRowTitleCellOpen ");
- sr.append(" style=\"");
- sr.append(style);
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatFieldRowTitleCellOpen(modelFormField));
}
@Override
public void renderFormatFieldRowTitleCellClose(Appendable writer,
Map<String, Object> context, ModelFormField modelFormField) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatFieldRowTitleCellClose />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatFieldRowTitleCellClose());
}
@Override
@@ -848,30 +601,18 @@ public final class MacroFormRenderer implements
FormStringRenderer {
@Override
public void renderFormatFieldRowWidgetCellOpen(Appendable writer,
Map<String, Object> context, ModelFormField modelFormField, int positions,
int positionSpan, Integer
nextPositionInRow) throws IOException {
- String areaStyle = modelFormField.getWidgetAreaStyle();
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatFieldRowWidgetCellOpen ");
- sr.append(" positionSpan=");
- sr.append(Integer.toString(positionSpan));
- sr.append(" style=\"");
- sr.append(areaStyle);
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatFieldRowWidgetCellOpen(modelFormField,
positionSpan));
}
@Override
public void renderFormatFieldRowWidgetCellClose(Appendable writer,
Map<String, Object> context, ModelFormField modelFormField, int positions,
int positionSpan, Integer
nextPositionInRow) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatFieldRowWidgetCellClose />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatFieldRowWidgetCellClose());
}
@Override
public void renderFormatEmptySpace(Appendable writer, Map<String, Object>
context, ModelForm modelForm) throws IOException {
- StringWriter sr = new StringWriter();
- sr.append("<@renderFormatEmptySpace />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.formatEmptySpace());
}
@Override
@@ -1743,16 +1484,8 @@ public final class MacroFormRenderer implements
FormStringRenderer {
*/
public void renderBeginningBoundaryComment(Appendable writer, String
widgetType, ModelWidget modelWidget) {
if (this.widgetCommentsEnabled) {
- StringWriter sr = new StringWriter();
- sr.append("<@formatBoundaryComment ");
- sr.append(" boundaryType=\"");
- sr.append("Begin");
- sr.append("\" widgetType=\"");
- sr.append(widgetType);
- sr.append("\" widgetName=\"");
- sr.append(modelWidget.getBoundaryCommentName());
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.boundaryComment("Begin", widgetType,
+ modelWidget.getBoundaryCommentName()));
}
}
@@ -1764,16 +1497,8 @@ public final class MacroFormRenderer implements
FormStringRenderer {
*/
public void renderEndingBoundaryComment(Appendable writer, String
widgetType, ModelWidget modelWidget) {
if (this.widgetCommentsEnabled) {
- StringWriter sr = new StringWriter();
- sr.append("<@formatBoundaryComment ");
- sr.append(" boundaryType=\"");
- sr.append("End");
- sr.append("\" widgetType=\"");
- sr.append(widgetType);
- sr.append("\" widgetName=\"");
- sr.append(modelWidget.getBoundaryCommentName());
- sr.append("\" />");
- executeMacro(writer, sr.toString());
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.boundaryComment("End", widgetType,
+ modelWidget.getBoundaryCommentName()));
}
}
@@ -1854,23 +1579,10 @@ public final class MacroFormRenderer implements
FormStringRenderer {
writeFtlElement(writer,
renderableFtlFormElementsBuilder.tooltip(context, modelFormField));
}
- public void makeHyperlinkString(Appendable writer,
ModelFormField.SubHyperlink subHyperlink, Map<String, Object> context) throws
IOException {
- if (subHyperlink == null) {
- return;
- }
- if (subHyperlink.shouldUse(context)) {
- if (UtilValidate.isNotEmpty(subHyperlink.getWidth())) {
- this.request.setAttribute("width", subHyperlink.getWidth());
- }
- if (UtilValidate.isNotEmpty(subHyperlink.getHeight())) {
- this.request.setAttribute("height", subHyperlink.getHeight());
- }
+ private void makeHyperlinkString(Appendable writer,
ModelFormField.SubHyperlink subHyperlink, Map<String, Object> context) throws
IOException {
+ if (subHyperlink != null && subHyperlink.shouldUse(context)) {
writer.append(' ');
- makeHyperlinkByType(writer, subHyperlink.getLinkType(),
subHyperlink.getStyle(context), subHyperlink.getUrlMode(),
- subHyperlink.getTarget(context),
subHyperlink.getParameterMap(context,
subHyperlink.getModelFormField().getEntityName(),
-
subHyperlink.getModelFormField().getServiceName()),
subHyperlink.getDescription(context),
- subHyperlink.getTargetWindow(context), "",
subHyperlink.getModelFormField(), this.request, this.response,
- context);
+ writeFtlElement(writer,
renderableFtlFormElementsBuilder.makeHyperlinkString(subHyperlink, context));
}
}
@@ -1886,203 +1598,6 @@ public final class MacroFormRenderer implements
FormStringRenderer {
writer.append(location);
}
- public void makeHyperlinkByType(Appendable writer, String linkType, String
linkStyle, String targetType, String target, Map<String,
- String> parameterMap, String description, String targetWindow,
String confirmation, ModelFormField modelFormField,
- HttpServletRequest request, HttpServletResponse response,
Map<String, Object> context) throws IOException {
- String realLinkType = WidgetWorker.determineAutoLinkType(linkType,
target, targetType, request);
- UtilCodec.SimpleEncoder simpleEncoder = null;
- String encodedDescription = null;
- if
(description.equals(StringEscapeUtils.unescapeEcmaScript(StringEscapeUtils.unescapeHtml4(description))))
{
- simpleEncoder = internalEncoder;
- } else {
- simpleEncoder = UtilCodec.getEncoder("string");
- }
- if (simpleEncoder != null) {
- encodedDescription = simpleEncoder.encode(description);
- }
- // get the parameterized pagination index and size fields
- int paginatorNumber = WidgetWorker.getPaginatorNumber(context);
- ModelForm modelForm = modelFormField.getModelForm();
- ModelTheme modelTheme = visualTheme.getModelTheme();
- String viewIndexField = modelForm.getMultiPaginateIndexField(context);
- String viewSizeField = modelForm.getMultiPaginateSizeField(context);
- int viewIndex = Paginator.getViewIndex(modelForm, context);
- int viewSize = Paginator.getViewSize(modelForm, context);
- if (("viewIndex" + "_" + paginatorNumber).equals(viewIndexField)) {
- viewIndexField = "VIEW_INDEX" + "_" + paginatorNumber;
- }
- if (("viewSize" + "_" + paginatorNumber).equals(viewSizeField)) {
- viewSizeField = "VIEW_SIZE" + "_" + paginatorNumber;
- }
- if ("hidden-form".equals(realLinkType)) {
- parameterMap.put(viewIndexField, Integer.toString(viewIndex));
- parameterMap.put(viewSizeField, Integer.toString(viewSize));
- if ("multi".equals(modelForm.getType())) {
- final Element anchorElement =
WidgetWorker.makeHiddenFormLinkAnchorElement(linkStyle,
- encodedDescription, confirmation, modelFormField,
request, context);
- writer.append(anchorElement.outerHtml());
- // this is a bit trickier, since we can't do a nested form
we'll have to put the link to submit the form in place,
- // but put the actual form def elsewhere, ie after the big
form is closed
- Map<String, Object> wholeFormContext =
UtilGenerics.cast(context.get("wholeFormContext"));
- Appendable postMultiFormWriter = wholeFormContext != null ?
(Appendable) wholeFormContext.get("postMultiFormWriter") : null;
- if (postMultiFormWriter == null) {
- postMultiFormWriter = new StringWriter();
- wholeFormContext.put("postMultiFormWriter",
postMultiFormWriter);
- }
- final Element hiddenFormElement =
WidgetWorker.makeHiddenFormLinkFormElement(target, targetType,
- targetWindow, parameterMap, modelFormField, request,
response, context);
- postMultiFormWriter.append(hiddenFormElement.outerHtml());
-
- } else {
- final Element hiddenFormElement =
WidgetWorker.makeHiddenFormLinkFormElement(target, targetType,
- targetWindow, parameterMap, modelFormField, request,
response, context);
- writer.append(hiddenFormElement.outerHtml());
- final Element anchorElement =
WidgetWorker.makeHiddenFormLinkAnchorElement(linkStyle,
- encodedDescription, confirmation, modelFormField,
request, context);
- if (anchorElement != null) {
- writer.append(anchorElement.outerHtml());
- }
- }
- } else {
- if ("layered-modal".equals(realLinkType)) {
- String uniqueItemName = UtilRandom.getUnique("Modal_", true);
- String width = (String) this.request.getAttribute("width");
- if (UtilValidate.isEmpty(width)) {
- width =
String.valueOf(modelTheme.getLinkDefaultLayeredModalWidth());
- this.request.setAttribute("width", width);
- }
- String height = (String) this.request.getAttribute("height");
- if (UtilValidate.isEmpty(height)) {
- height =
String.valueOf(modelTheme.getLinkDefaultLayeredModalHeight());
- this.request.setAttribute("height", height);
- }
- this.request.setAttribute("uniqueItemName", uniqueItemName);
- makeHyperlinkString(writer, linkStyle, targetType, target,
parameterMap, encodedDescription, confirmation, modelFormField, request,
- response, context, targetWindow);
- this.request.removeAttribute("uniqueItemName");
- this.request.removeAttribute("height");
- this.request.removeAttribute("width");
- } else {
- makeHyperlinkString(writer, linkStyle, targetType, target,
parameterMap, encodedDescription, confirmation, modelFormField, request,
- response, context, targetWindow);
- }
- }
- }
-
- public void makeHyperlinkString(Appendable writer, String linkStyle,
String targetType, String target, Map<String, String> parameterMap,
- String description, String confirmation,
ModelFormField modelFormField, HttpServletRequest request,
- HttpServletResponse response, Map<String,
Object> context, String targetWindow) throws IOException {
- if (description != null ||
UtilValidate.isNotEmpty(request.getAttribute("image"))) {
- StringBuilder linkUrl = new StringBuilder();
- final URI linkUri = WidgetWorker.buildHyperlinkUri(target,
targetType,
-
UtilValidate.isEmpty(request.getAttribute("uniqueItemName")) ? parameterMap :
null,
- null, false, false, true, request, response);
- linkUrl.append(linkUri.toString());
- String event = "";
- String action = "";
- String imgSrc = "";
- String imgTitle = "";
- String alt = "";
- String id = "";
- String uniqueItemName = "";
- String width = "";
- String height = "";
- String title = "";
- String text = "";
- String hiddenFormName =
WidgetWorker.makeLinkHiddenFormName(context, modelFormField);
- if (UtilValidate.isNotEmpty(modelFormField.getEvent()) &&
UtilValidate.isNotEmpty(modelFormField.getAction(context))) {
- event = modelFormField.getEvent();
- action = modelFormField.getAction(context);
- }
- if (UtilValidate.isNotEmpty(request.getAttribute("image"))) {
- imgSrc = request.getAttribute("image").toString();
- }
- if (UtilValidate.isNotEmpty(request.getAttribute("imageTitle"))) {
- imgTitle = request.getAttribute("imageTitle").toString();
- }
- if (UtilValidate.isNotEmpty(request.getAttribute("alternate"))) {
- alt = request.getAttribute("alternate").toString();
- }
- int size = 0;
- if
(UtilValidate.isNotEmpty(request.getAttribute("descriptionSize"))) {
- size =
Integer.parseInt(request.getAttribute("descriptionSize").toString());
- }
- // if description is truncated, always use description as title
- if (UtilValidate.isNotEmpty(description) && size > 0 &&
description.length() > size) {
- title = description;
- description =
StringUtil.truncateEncodedStringToLength(description, size);
- } else if (UtilValidate.isNotEmpty(request.getAttribute("title")))
{
- title = request.getAttribute("title").toString();
- }
- if (UtilValidate.isNotEmpty(request.getAttribute("id"))) {
- id = request.getAttribute("id").toString();
- }
- if (UtilValidate.isNotEmpty(request.getAttribute("text"))) {
- text = request.getAttribute("text").toString();
- }
- if
(UtilValidate.isNotEmpty(request.getAttribute("uniqueItemName"))) {
- uniqueItemName =
request.getAttribute("uniqueItemName").toString();
- width = request.getAttribute("width").toString();
- height = request.getAttribute("height").toString();
- }
- StringBuilder targetParameters = new StringBuilder();
- if (UtilValidate.isNotEmpty(parameterMap) ||
UtilValidate.isNotEmpty(uniqueItemName)) {
- try {
- Map<String, Object> params = new java.util.TreeMap<>();
- if (UtilValidate.isNotEmpty(parameterMap)) {
- params.putAll(parameterMap);
- }
- if (UtilValidate.isNotEmpty(uniqueItemName)) {
- params.put("presentation", "layer");
- }
-
targetParameters.append(org.apache.ofbiz.base.lang.JSON.from(params).toString());
- } catch (Exception e) {
- Debug.logError(e, "Error converting dialog params to
JSON", MODULE);
- }
- }
- StringWriter sr = new StringWriter();
- sr.append("<@makeHyperlinkString ");
- sr.append("linkStyle=\"");
- sr.append(linkStyle == null ? "" : linkStyle);
- sr.append("\" hiddenFormName=\"");
- sr.append(hiddenFormName);
- sr.append("\" event=\"");
- sr.append(event);
- sr.append("\" action=\"");
- sr.append(action);
- sr.append("\" imgSrc=\"");
- sr.append(imgSrc);
- sr.append("\" imgTitle=\"");
- sr.append(imgTitle);
- sr.append("\" title=\"");
- sr.append(title);
- sr.append("\" alternate=\"");
- sr.append(alt);
- sr.append("\" targetParameters=\"");
-
sr.append(MacroCommonRenderer.escapeFtlString(targetParameters.toString()));
- sr.append("\" linkUrl=\"");
- sr.append(linkUrl.toString());
- sr.append("\" targetWindow=\"");
- sr.append(targetWindow);
- sr.append("\" description=\"");
- sr.append(description);
- sr.append("\" confirmation=\"");
- sr.append(confirmation);
- sr.append("\" uniqueItemName=\"");
- sr.append(uniqueItemName);
- sr.append("\" height=\"");
- sr.append(height);
- sr.append("\" width=\"");
- sr.append(width);
- sr.append("\" id=\"");
- sr.append(id);
- sr.append("\" text=\"");
- sr.append(text);
- sr.append("\" />");
- executeMacro(writer, sr.toString());
- }
- }
-
@Override
public void renderContainerFindField(Appendable writer, Map<String,
Object> context, ContainerField containerField) throws IOException {
final RenderableFtlMacroCall containerMc =
renderableFtlFormElementsBuilder.containerMacroCall(context, containerField);
diff --git
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java
index d5171cf636..539ad1d401 100644
---
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java
+++
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilder.java
@@ -39,6 +39,7 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import com.ibm.icu.util.Calendar;
+import org.apache.ofbiz.base.lang.JSON;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.StringUtil;
import org.apache.ofbiz.base.util.UtilCodec;
@@ -50,10 +51,12 @@ import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.UtilRandom;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.base.util.string.FlexibleStringExpander;
+import org.apache.ofbiz.security.CsrfUtil;
import org.apache.ofbiz.webapp.control.RequestHandler;
import org.apache.ofbiz.widget.WidgetWorker;
import org.apache.ofbiz.widget.content.StaticContentUrlProvider;
import org.apache.ofbiz.widget.model.CommonWidgetModels;
+import org.apache.ofbiz.widget.model.FieldInfo;
import org.apache.ofbiz.widget.model.ModelForm;
import org.apache.ofbiz.widget.model.ModelFormField;
import org.apache.ofbiz.widget.model.ModelFormField.ContainerField;
@@ -828,7 +831,9 @@ public final class RenderableFtlFormElementsBuilder {
if ("multi".equals(modelForm.getType())) {
final Element anchorElement =
WidgetWorker.makeHiddenFormLinkAnchorElement(linkStyle,
description, confirmation, modelFormField, request,
context);
- htmlStringBuilder.append(anchorElement.outerHtml());
+ if (anchorElement != null) {
+ htmlStringBuilder.append(anchorElement.outerHtml());
+ }
// this is a bit trickier, since we can't do a nested form
we'll have to put the link to submit the
// form in place, but put the actual form def elsewhere, ie
after the big form is closed
@@ -845,7 +850,9 @@ public final class RenderableFtlFormElementsBuilder {
htmlStringBuilder.append(hiddenFormElement.outerHtml());
final Element anchorElement =
WidgetWorker.makeHiddenFormLinkAnchorElement(linkStyle,
description, confirmation, modelFormField, request,
context);
- htmlStringBuilder.append(anchorElement.outerHtml());
+ if (anchorElement != null) {
+ htmlStringBuilder.append(anchorElement.outerHtml());
+ }
}
return renderableFtlStringBuilder.build();
@@ -898,6 +905,7 @@ public final class RenderableFtlFormElementsBuilder {
String width = "";
String height = "";
String title = "";
+ String text = "";
String hiddenFormName =
WidgetWorker.makeLinkHiddenFormName(context, modelFormField);
if (UtilValidate.isNotEmpty(modelFormField.getEvent())
&&
UtilValidate.isNotEmpty(modelFormField.getAction(context))) {
@@ -926,31 +934,51 @@ public final class RenderableFtlFormElementsBuilder {
if (UtilValidate.isNotEmpty(request.getAttribute("id"))) {
id = request.getAttribute("id").toString();
}
+ if (UtilValidate.isNotEmpty(request.getAttribute("text"))) {
+ text = request.getAttribute("text").toString();
+ }
if
(UtilValidate.isNotEmpty(request.getAttribute("uniqueItemName"))) {
uniqueItemName =
request.getAttribute("uniqueItemName").toString();
width = request.getAttribute("width").toString();
height = request.getAttribute("height").toString();
}
+ // the macro expects the parameters of the link as a JSON string
+ String targetParameters = "";
+ if (UtilValidate.isNotEmpty(parameterMap) ||
UtilValidate.isNotEmpty(uniqueItemName)) {
+ try {
+ final Map<String, Object> params = new
java.util.TreeMap<>();
+ if (UtilValidate.isNotEmpty(parameterMap)) {
+ params.putAll(parameterMap);
+ }
+ if (UtilValidate.isNotEmpty(uniqueItemName)) {
+ params.put("presentation", "layer");
+ }
+ targetParameters = JSON.from(params).toString();
+ } catch (Exception e) {
+ Debug.logError(e, "Error converting dialog params to
JSON", MODULE);
+ }
+ }
return RenderableFtlMacroCall.builder()
.name("makeHyperlinkString")
.stringParameter("linkStyle", linkStyle == null ? "" :
linkStyle)
- .stringParameter("hiddenFormName", hiddenFormName)
+ .stringParameter("hiddenFormName", nonNull(hiddenFormName))
.stringParameter("event", event)
.stringParameter("action", action)
.stringParameter("imgSrc", imgSrc)
.stringParameter("imgTitle", imgTitle)
.stringParameter("title", title)
.stringParameter("alternate", alt)
- .mapParameter("targetParameters", parameterMap)
+ .stringParameter("targetParameters", targetParameters)
.stringParameter("linkUrl", linkUrl.toString())
- .stringParameter("targetWindow", targetWindow)
- .stringParameter("description", description)
- .stringParameter("confirmation", confirmation)
+ .stringParameter("targetWindow", nonNull(targetWindow))
+ .stringParameter("description", nonNull(description))
+ .stringParameter("confirmation", nonNull(confirmation))
.stringParameter("uniqueItemName", uniqueItemName)
.stringParameter("height", height)
.stringParameter("width", width)
.stringParameter("id", id)
+ .stringParameter("text", text)
.build();
} else {
return RenderableFtlNoop.INSTANCE;
@@ -1549,6 +1577,309 @@ public final class RenderableFtlFormElementsBuilder {
return builder.build();
}
+ /**
+ * Creates the macro call that opens a form.
+ * @param context the context
+ * @param modelForm the form
+ * @return the RenderableFtl
+ */
+ public RenderableFtl formOpen(final Map<String, Object> context, final
ModelForm modelForm) {
+ final String targetType = modelForm.getTargetType();
+ final String target = modelForm.getTarget(context, targetType);
+ String linkUrl = "";
+ if (UtilValidate.isNotEmpty(target)) {
+ linkUrl = WidgetWorker.buildHyperlinkUri(target, targetType, null,
null, false, false, true,
+ request, response).toString();
+ }
+ String hasRequiredField = "";
+ for (final ModelFormField formField : modelForm.getFieldList()) {
+ if (formField.getRequiredField()) {
+ hasRequiredField = "Y";
+ break;
+ }
+ }
+ // Generate CSRF name & value for form
+ final String csrfNameValue = CsrfUtil.getTokenNameNonAjax() + " " +
CsrfUtil.generateTokenForNonAjax(request, target);
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormOpen")
+ .stringParameter("linkUrl", linkUrl)
+ .stringParameter("formType", nonNull(modelForm.getType()))
+ .stringParameter("targetWindow",
nonNull(modelForm.getTargetWindow(context)))
+ .stringParameter("containerId",
nonNull(FormRenderer.getCurrentContainerId(modelForm, context)))
+ .stringParameter("containerStyle",
nonNull(modelForm.getContainerStyle()))
+ .stringParameter("autocomplete",
modelForm.getClientAutocompleteFields() ? "" : "off")
+ .stringParameter("name",
nonNull(FormRenderer.getCurrentFormName(modelForm, context)))
+ .stringParameter("focusFieldName",
nonNull(modelForm.getFocusFieldName()))
+ .stringParameter("hasRequiredField", hasRequiredField)
+ .stringParameter("viewIndexField",
nonNull(modelForm.getMultiPaginateIndexField(context)))
+ .stringParameter("viewSizeField",
nonNull(modelForm.getMultiPaginateSizeField(context)))
+ .stringParameter("viewIndex",
Integer.toString(Paginator.getViewIndex(modelForm, context)))
+ .stringParameter("viewSize",
Integer.toString(Paginator.getViewSize(modelForm, context)))
+ .booleanParameter("useRowSubmit", modelForm.getUseRowSubmit())
+ .stringParameter("csrfNameValue", csrfNameValue)
+ .build();
+ }
+
+ /**
+ * Creates the macro call that closes a form.
+ * @return the RenderableFtl
+ */
+ public RenderableFtl formClose() {
+ return macroWithoutParameters("renderFormClose");
+ }
+
+ /**
+ * Creates the macro call that closes a multi form.
+ * @return the RenderableFtl
+ */
+ public RenderableFtl multiFormClose() {
+ return macroWithoutParameters("renderMultiFormClose");
+ }
+
+ /**
+ * Gets what has to be rendered after the closing of a multi form, such as
the forms of the hidden form links.
+ * @param context the context
+ * @return the RenderableFtl, which renders nothing if there is none
+ */
+ public RenderableFtl postMultiFormContent(final Map<String, Object>
context) {
+ final Map<String, Object> wholeFormContext =
UtilGenerics.cast(context.get("wholeFormContext"));
+ final RenderableFtl postMultiFormContent = wholeFormContext == null ?
null
+ : (RenderableFtl)
wholeFormContext.get("postMultiFormRenderableFtl");
+ return postMultiFormContent == null ? RenderableFtlNoop.INSTANCE :
postMultiFormContent;
+ }
+
+ /**
+ * Creates the macro call that opens the wrapper of a list form.
+ * @param context the context
+ * @param modelForm the form
+ * @return the RenderableFtl
+ */
+ public RenderableFtl formatListWrapperOpen(final Map<String, Object>
context, final ModelForm modelForm) {
+ final List<String> columnStyleList = new ArrayList<>();
+ final List<String> fieldNameList = new ArrayList<>();
+ for (final ModelFormField childField : modelForm.getFieldList()) {
+ final int childFieldType =
childField.getFieldInfo().getFieldType();
+ if (childFieldType == FieldInfo.HIDDEN || childFieldType ==
FieldInfo.IGNORED) {
+ continue;
+ }
+ final String areaStyle = nonNull(childField.getTitleAreaStyle());
+ if (fieldNameList.contains(childField.getName())) {
+ if (UtilValidate.isNotEmpty(areaStyle)) {
+
columnStyleList.set(fieldNameList.indexOf(childField.getName()), areaStyle);
+ }
+ } else {
+ columnStyleList.add(areaStyle);
+ fieldNameList.add(childField.getName());
+ }
+ }
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatListWrapperOpen")
+ .stringParameter("formName", nonNull(modelForm.getName()))
+ .stringParameter("style",
FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context))
+ .objectParameter("columnStyles", columnStyleList)
+ .build();
+ }
+
+ /**
+ * Creates the macro call that renders the message of a form without data.
+ * @param context the context
+ * @param modelForm the form
+ * @return the RenderableFtl
+ */
+ public RenderableFtl emptyFormDataMessage(final Map<String, Object>
context, final ModelForm modelForm) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderEmptyFormDataMessage")
+ .stringParameter("message",
nonNull(modelForm.getEmptyFormDataMessage(context)))
+ .build();
+ }
+
+ /**
+ * Creates the macro call that closes the wrapper of a list form.
+ * @param modelForm the form
+ * @return the RenderableFtl
+ */
+ public RenderableFtl formatListWrapperClose(final ModelForm modelForm) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatListWrapperClose")
+ .stringParameter("formName", nonNull(modelForm.getName()))
+ .build();
+ }
+
+ public RenderableFtl formatHeaderOpen() {
+ return macroWithoutParameters("renderFormatHeaderOpen");
+ }
+
+ public RenderableFtl formatHeaderClose() {
+ return macroWithoutParameters("renderFormatHeaderClose");
+ }
+
+ public RenderableFtl formatHeaderRowOpen(final Map<String, Object>
context, final ModelForm modelForm) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatHeaderRowOpen")
+ .stringParameter("style",
FlexibleStringExpander.expandString(modelForm.getHeaderRowStyle(), context))
+ .build();
+ }
+
+ public RenderableFtl formatHeaderRowClose() {
+ return macroWithoutParameters("renderFormatHeaderRowClose");
+ }
+
+ public RenderableFtl formatHeaderRowCellOpen(final ModelFormField
modelFormField, final int positionSpan) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatHeaderRowCellOpen")
+ .stringParameter("style",
nonNull(modelFormField.getTitleAreaStyle()))
+ .intParameter("positionSpan", positionSpan)
+ .build();
+ }
+
+ public RenderableFtl formatHeaderRowCellClose() {
+ return macroWithoutParameters("renderFormatHeaderRowCellClose");
+ }
+
+ public RenderableFtl formatHeaderRowFormCellOpen(final ModelForm
modelForm) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatHeaderRowFormCellOpen")
+ .stringParameter("style",
nonNull(modelForm.getFormTitleAreaStyle()))
+ .build();
+ }
+
+ public RenderableFtl formatHeaderRowFormCellClose() {
+ return macroWithoutParameters("renderFormatHeaderRowFormCellClose");
+ }
+
+ public RenderableFtl formatHeaderRowFormCellTitleSeparator(final
ModelFormField modelFormField, final boolean isLast) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatHeaderRowFormCellTitleSeparator")
+ .stringParameter("style",
nonNull(modelFormField.getTitleStyle()))
+ .booleanParameter("isLast", isLast)
+ .build();
+ }
+
+ public RenderableFtl formatItemRowOpen(final Map<String, Object> context,
final ModelForm modelForm) {
+ final Integer itemIndex = (Integer) context.get("itemIndex");
+ String altRowStyles = "";
+ String evenRowStyle = "";
+ String oddRowStyle = "";
+ if (itemIndex != null) {
+ altRowStyles = modelForm.getStyleAltRowStyle(context);
+ if (itemIndex % 2 == 0) {
+ evenRowStyle = modelForm.getEvenRowStyle();
+ } else {
+ oddRowStyle =
FlexibleStringExpander.expandString(modelForm.getOddRowStyle(), context);
+ }
+ }
+ final RenderableFtlMacroCallBuilder builder =
RenderableFtlMacroCall.builder()
+ .name("renderFormatItemRowOpen")
+ .stringParameter("formName", nonNull(modelForm.getName()))
+ .stringParameter("altRowStyles", nonNull(altRowStyles))
+ .stringParameter("evenRowStyle", nonNull(evenRowStyle))
+ .stringParameter("oddRowStyle", nonNull(oddRowStyle));
+ if (itemIndex != null) {
+ builder.intParameter("itemIndex", itemIndex);
+ }
+ return builder.build();
+ }
+
+ public RenderableFtl formatItemRowClose(final ModelForm modelForm) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatItemRowClose")
+ .stringParameter("formName", nonNull(modelForm.getName()))
+ .build();
+ }
+
+ public RenderableFtl formatItemRowCellOpen(final ModelFormField
modelFormField, final int positionSpan) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatItemRowCellOpen")
+ .stringParameter("fieldName",
nonNull(modelFormField.getName()))
+ .stringParameter("style",
nonNull(modelFormField.getWidgetAreaStyle()))
+ .intParameter("positionSpan", positionSpan)
+ .build();
+ }
+
+ public RenderableFtl formatItemRowCellClose(final ModelFormField
modelFormField) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatItemRowCellClose")
+ .stringParameter("fieldName",
nonNull(modelFormField.getName()))
+ .build();
+ }
+
+ public RenderableFtl formatItemRowFormCellOpen(final ModelForm modelForm) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatItemRowFormCellOpen")
+ .stringParameter("style",
nonNull(modelForm.getFormTitleAreaStyle()))
+ .build();
+ }
+
+ public RenderableFtl formatItemRowFormCellClose() {
+ return macroWithoutParameters("renderFormatItemRowFormCellClose");
+ }
+
+ public RenderableFtl formatSingleWrapperOpen(final Map<String, Object>
context, final ModelForm modelForm) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatSingleWrapperOpen")
+ .stringParameter("formName", nonNull(modelForm.getName()))
+ .stringParameter("style",
FlexibleStringExpander.expandString(modelForm.getDefaultTableStyle(), context))
+ .build();
+ }
+
+ public RenderableFtl formatSingleWrapperClose(final ModelForm modelForm) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatSingleWrapperClose")
+ .stringParameter("formName", nonNull(modelForm.getName()))
+ .build();
+ }
+
+ public RenderableFtl formatFieldRowOpen() {
+ return macroWithoutParameters("renderFormatFieldRowOpen");
+ }
+
+ public RenderableFtl formatFieldRowClose() {
+ return macroWithoutParameters("renderFormatFieldRowClose");
+ }
+
+ public RenderableFtl formatFieldRowTitleCellOpen(final ModelFormField
modelFormField) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatFieldRowTitleCellOpen")
+ .stringParameter("style",
nonNull(modelFormField.getTitleAreaStyle()))
+ .build();
+ }
+
+ public RenderableFtl formatFieldRowTitleCellClose() {
+ return macroWithoutParameters("renderFormatFieldRowTitleCellClose");
+ }
+
+ public RenderableFtl formatFieldRowWidgetCellOpen(final ModelFormField
modelFormField, final int positionSpan) {
+ return RenderableFtlMacroCall.builder()
+ .name("renderFormatFieldRowWidgetCellOpen")
+ .intParameter("positionSpan", positionSpan)
+ .stringParameter("style",
nonNull(modelFormField.getWidgetAreaStyle()))
+ .build();
+ }
+
+ public RenderableFtl formatFieldRowWidgetCellClose() {
+ return macroWithoutParameters("renderFormatFieldRowWidgetCellClose");
+ }
+
+ /**
+ * Creates the macro call that renders a boundary comment.
+ * @param boundaryType Begin or End
+ * @param widgetType the type of the widget, such as Form Widget - Form
Element
+ * @param widgetName the name of the widget
+ * @return the RenderableFtl
+ */
+ public RenderableFtl boundaryComment(final String boundaryType, final
String widgetType, final String widgetName) {
+ return RenderableFtlMacroCall.builder()
+ .name("formatBoundaryComment")
+ .stringParameter("boundaryType", boundaryType)
+ .stringParameter("widgetType", widgetType)
+ .stringParameter("widgetName", nonNull(widgetName))
+ .build();
+ }
+
+ private static RenderableFtl macroWithoutParameters(final String
macroName) {
+ return RenderableFtlMacroCall.builder().name(macroName).build();
+ }
+
private static String nonNull(final String value) {
return value == null ? "" : value;
}
diff --git
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/renderable/RenderableFtlString.java
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/renderable/RenderableFtlString.java
index 4c718fcf27..eb251ed9f5 100644
---
a/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/renderable/RenderableFtlString.java
+++
b/framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/macro/renderable/RenderableFtlString.java
@@ -21,6 +21,10 @@ package org.apache.ofbiz.widget.renderer.macro.renderable;
import java.util.Locale;
import java.util.function.Consumer;
+/**
+ * Finished output, such as the HTML of a link, that is written as it is. It
is not a template: nothing in it is
+ * interpreted, so it can hold values of the data.
+ */
public final class RenderableFtlString implements RenderableFtl {
private final String ftlString;
diff --git
a/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/FtlWriterTest.java
b/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/FtlWriterTest.java
new file mode 100644
index 0000000000..e51d501c76
--- /dev/null
+++
b/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/FtlWriterTest.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+
*******************************************************************************/
+package org.apache.ofbiz.widget.renderer.macro;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyMap;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import java.io.StringWriter;
+
+import org.apache.ofbiz.base.util.template.FreeMarkerWorker;
+import org.apache.ofbiz.widget.renderer.macro.renderable.RenderableFtlString;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import freemarker.core.Environment;
+import freemarker.template.Template;
+
+public final class FtlWriterTest {
+
+ private final Template template = mock(Template.class);
+ private final Environment environment = mock(Environment.class);
+
+ private MockedStatic<FreeMarkerWorker> freeMarkerWorkerMock;
+
+ @BeforeEach
+ public void setupMockups() {
+ freeMarkerWorkerMock = mockStatic(FreeMarkerWorker.class,
CALLS_REAL_METHODS);
+ freeMarkerWorkerMock.when(() ->
FreeMarkerWorker.getTemplate(anyString())).thenReturn(template);
+ freeMarkerWorkerMock.when(() ->
FreeMarkerWorker.renderTemplate(any(Template.class), anyMap(),
any())).thenReturn(environment);
+ }
+
+ @AfterEach
+ public void tearDownMockups() {
+ freeMarkerWorkerMock.close();
+ }
+
+ @Test
+ public void renderableFtlStringIsWrittenAsItIsAndNeverCompiled() throws
Exception {
+ final FtlWriter ftlWriter = new FtlWriter("LIBRARY");
+ final StringWriter writer = new StringWriter();
+ final String html = "<a href=\"#\">${1+1} <#stop \"stopped\">
#{2}</a>";
+
+ ftlWriter.processFtl(writer, null, new RenderableFtlString(html));
+
+ assertThat(writer.toString(), equalTo(html));
+ // a compiled string would have been included in the environment of
the writer
+ verify(environment, never()).include(any(Template.class));
+ }
+}
diff --git
a/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRendererTest.java
b/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRendererTest.java
index ab1574b133..fe7e566970 100644
---
a/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRendererTest.java
+++
b/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/MacroFormRendererTest.java
@@ -20,6 +20,7 @@ package org.apache.ofbiz.widget.renderer.macro;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
@@ -35,8 +36,10 @@ import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -55,7 +58,6 @@ import jakarta.servlet.http.HttpSession;
import org.apache.ofbiz.base.util.UtilHttp;
import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.template.FreeMarkerWorker;
-import org.apache.ofbiz.webapp.control.ConfigXMLReader;
import org.apache.ofbiz.webapp.control.RequestHandler;
import org.apache.ofbiz.widget.model.FieldInfo;
import org.apache.ofbiz.widget.model.ModelForm;
@@ -71,6 +73,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.MockedStatic;
import com.google.common.collect.ImmutableMap;
@@ -356,108 +359,134 @@ public final class MacroFormRendererTest {
@Test
public void formOpenedMacroRendered() throws IOException {
final ModelSingleForm modelSingleForm = mock(ModelSingleForm.class);
- when(modelSingleForm.getType()).thenReturn("single");
+ when(renderableFtlFormElementsBuilder.formOpen(notNull(),
eq(modelSingleForm))).thenReturn(genericMacroCall);
macroFormRenderer.renderFormOpen(appendable, ImmutableMap.of(),
modelSingleForm);
- assertAndGetMacroString("renderFormOpen", ImmutableMap.of("formType",
"single"));
+
+ genericSingleMacroRenderedVerification();
}
@Test
public void formClosedMacroRendered() throws IOException {
final ModelSingleForm modelSingleForm = mock(ModelSingleForm.class);
+
when(renderableFtlFormElementsBuilder.formClose()).thenReturn(genericMacroCall);
+
macroFormRenderer.renderFormClose(appendable, ImmutableMap.of(),
modelSingleForm);
- assertAndGetMacroString("renderFormClose");
+
+ genericSingleMacroRenderedVerification();
}
@Test
- public void multiFormClosedMacroRendered() throws IOException {
+ public void multiFormClosedMacroRenderedBeforeThePostFormContent() throws
IOException {
final ModelForm modelForm = mock(ModelForm.class);
+
when(renderableFtlFormElementsBuilder.multiFormClose()).thenReturn(genericMacroCall);
+
when(renderableFtlFormElementsBuilder.postMultiFormContent(notNull())).thenReturn(genericHyperlinkMacroCall);
+
macroFormRenderer.renderMultiFormClose(appendable, ImmutableMap.of(),
modelForm);
- assertAndGetMacroString("renderMultiFormClose");
+
+ final InOrder inOrder = inOrder(ftlWriter);
+ inOrder.verify(ftlWriter).processFtl(appendable, null,
genericMacroCall);
+ inOrder.verify(ftlWriter).processFtl(appendable, null,
genericHyperlinkMacroCall);
}
@Test
public void listWrapperOpenMacroRendered() throws IOException {
final ModelSingleForm modelSingleForm = mock(ModelSingleForm.class);
+ when(renderableFtlFormElementsBuilder.formatListWrapperOpen(notNull(),
eq(modelSingleForm))).thenReturn(genericMacroCall);
+
macroFormRenderer.setRenderPagination(false);
macroFormRenderer.renderFormatListWrapperOpen(appendable, new
HashMap<>(), modelSingleForm);
- assertAndGetMacroString("renderFormatListWrapperOpen");
+
+ genericSingleMacroRenderedVerification();
}
@Test
public void emptyFormDataMacroRendered() throws IOException {
final ModelSingleForm modelSingleForm = mock(ModelSingleForm.class);
-
when(modelSingleForm.getEmptyFormDataMessage(notNull())).thenReturn("EMPTY");
+ when(renderableFtlFormElementsBuilder.emptyFormDataMessage(notNull(),
eq(modelSingleForm))).thenReturn(genericMacroCall);
macroFormRenderer.renderEmptyFormDataMessage(appendable, new
HashMap<>(), modelSingleForm);
- assertAndGetMacroString("renderEmptyFormDataMessage",
ImmutableMap.of("message", "EMPTY"));
+
+ genericSingleMacroRenderedVerification();
}
@Test
public void listWrapperCloseMacroRendered() throws IOException {
final ModelSingleForm modelSingleForm = mock(ModelSingleForm.class);
+
when(renderableFtlFormElementsBuilder.formatListWrapperClose(modelSingleForm)).thenReturn(genericMacroCall);
+
macroFormRenderer.setRenderPagination(false);
macroFormRenderer.renderFormatListWrapperClose(appendable, new
HashMap<>(), modelSingleForm);
- assertAndGetMacroString("renderFormatListWrapperClose");
+
+ genericSingleMacroRenderedVerification();
}
@Test
public void itemRowOpenMacroRendered() throws IOException {
final ModelForm modelForm = mock(ModelForm.class);
- when(modelForm.getName()).thenReturn("FORMNAME");
- when(modelForm.getEvenRowStyle()).thenReturn("EVENSTYLE");
+ when(renderableFtlFormElementsBuilder.formatItemRowOpen(notNull(),
eq(modelForm))).thenReturn(genericMacroCall);
macroFormRenderer.renderFormatItemRowOpen(appendable,
ImmutableMap.of("itemIndex", 2), modelForm);
- assertAndGetMacroString("renderFormatItemRowOpen", ImmutableMap.of(
- "formName", "FORMNAME",
- "itemIndex", 2,
- "evenRowStyle", "EVENSTYLE"));
+
+ genericSingleMacroRenderedVerification();
}
@Test
public void itemRowCellOpenMacroRendered() throws IOException {
final ModelForm modelForm = mock(ModelForm.class);
final ModelFormField localModelFormField = mock(ModelFormField.class);
- when(localModelFormField.getWidgetAreaStyle()).thenReturn("AREASTYLE");
- when(localModelFormField.getName()).thenReturn("FIELDNAME");
+
when(renderableFtlFormElementsBuilder.formatItemRowCellOpen(localModelFormField,
2)).thenReturn(genericMacroCall);
macroFormRenderer.renderFormatItemRowCellOpen(appendable,
ImmutableMap.of(), modelForm, localModelFormField, 2);
- assertAndGetMacroString("renderFormatItemRowCellOpen", ImmutableMap.of(
- "fieldName", "FIELDNAME",
- "positionSpan", 2,
- "style", "AREASTYLE"));
+
+ genericSingleMacroRenderedVerification();
}
@Test
public void itemRowFormCellOpenMacroRendered() throws IOException {
final ModelForm modelForm = mock(ModelForm.class);
- when(modelForm.getFormTitleAreaStyle()).thenReturn("AREASTYLE");
+
when(renderableFtlFormElementsBuilder.formatItemRowFormCellOpen(modelForm)).thenReturn(genericMacroCall);
macroFormRenderer.renderFormatItemRowFormCellOpen(appendable,
ImmutableMap.of(), modelForm);
- assertAndGetMacroString("renderFormatItemRowFormCellOpen",
ImmutableMap.of("style", "AREASTYLE"));
+
+ genericSingleMacroRenderedVerification();
}
@Test
public void singleWrapperOpenMacroRendered() throws IOException {
final ModelForm modelForm = mock(ModelForm.class);
-
when(modelForm.getDefaultTableStyle()).thenReturn("STYLE${styleParam}");
- when(modelForm.getName()).thenReturn("FORMNAME");
+
when(renderableFtlFormElementsBuilder.formatSingleWrapperOpen(notNull(),
eq(modelForm))).thenReturn(genericMacroCall);
+
+ macroFormRenderer.renderFormatSingleWrapperOpen(appendable,
ImmutableMap.of(), modelForm);
- macroFormRenderer.renderFormatSingleWrapperOpen(appendable,
ImmutableMap.of("styleParam", "ABCD"), modelForm);
- assertAndGetMacroString("renderFormatSingleWrapperOpen",
ImmutableMap.of(
- "formName", "FORMNAME",
- "style", "STYLEABCD"));
+ genericSingleMacroRenderedVerification();
}
@Test
public void fieldRowWidgetCellOpenMacroRendered() throws IOException {
final ModelFormField localModelFormField = mock(ModelFormField.class);
- when(localModelFormField.getWidgetAreaStyle()).thenReturn("AREASTYLE");
+
when(renderableFtlFormElementsBuilder.formatFieldRowWidgetCellOpen(localModelFormField,
1)).thenReturn(genericMacroCall);
macroFormRenderer.renderFormatFieldRowWidgetCellOpen(appendable,
ImmutableMap.of(), localModelFormField, 1, 1, null);
- assertAndGetMacroString("renderFormatFieldRowWidgetCellOpen",
ImmutableMap.of(
- "positionSpan", 1,
- "style", "AREASTYLE"));
+
+ genericSingleMacroRenderedVerification();
+ }
+
+ @Test
+ public void boundaryCommentsRenderedOnlyWhenEnabled() throws IOException {
+ final ModelSingleForm modelSingleForm = mock(ModelSingleForm.class);
+ when(modelSingleForm.getBoundaryCommentName()).thenReturn("FORMNAME");
+ when(renderableFtlFormElementsBuilder.formOpen(notNull(),
eq(modelSingleForm))).thenReturn(genericMacroCall);
+ when(renderableFtlFormElementsBuilder.boundaryComment("Begin", "Form
Widget - Form Element", "FORMNAME"))
+ .thenReturn(genericTooltipMacroCall);
+
+ utilPropertiesMock.when(() ->
UtilProperties.getPropertyValue("widget",
"widget.verbose")).thenReturn("false");
+ macroFormRenderer.renderFormOpen(appendable, ImmutableMap.of(),
modelSingleForm);
+ verify(ftlWriter, never()).processFtl(appendable, null,
genericTooltipMacroCall);
+
+ utilPropertiesMock.when(() ->
UtilProperties.getPropertyValue("widget", "widget.verbose")).thenReturn("true");
+ macroFormRenderer.renderFormOpen(appendable, ImmutableMap.of(),
modelSingleForm);
+ verify(ftlWriter).processFtl(appendable, null,
genericTooltipMacroCall);
}
@Test
@@ -692,94 +721,50 @@ public final class MacroFormRendererTest {
}
@Test
- public void hyperlinkFieldMacroRenderedTitleNotTruncated() throws
IOException {
+ public void hyperlinkFieldRendersHyperlinkWithTooltip() throws IOException
{
final ModelFormField.HyperlinkField hyperlinkField =
mock(ModelFormField.HyperlinkField.class);
- when(hyperlinkField.getModelFormField()).thenReturn(modelFormField);
- final String description = "DESCRIPTION";
- final String title = "TITLE";
-
- when(hyperlinkField.getDescription(notNull())).thenReturn(description);
- when(hyperlinkField.getTarget(notNull())).thenReturn("#");
- when(request.getAttribute("title")).thenReturn(title);
+
when(renderableFtlFormElementsBuilder.makeHyperlinkByType(nullable(String.class),
nullable(String.class),
+ nullable(String.class), nullable(String.class), anyMap(),
nullable(String.class), nullable(String.class),
+ nullable(String.class), eq(modelFormField), eq(request),
eq(response), notNull()))
+ .thenReturn(genericHyperlinkMacroCall);
+ genericTooltipRenderedExpectation(hyperlinkField);
macroFormRenderer.renderHyperlinkField(appendable, new HashMap<>(),
hyperlinkField);
- assertAndGetMacroString("makeHyperlinkString",
ImmutableMap.of("description", description, "title", title));
- }
- @Test
- public void hyperlinkFieldMacroRenderedTruncatedNoTitle() throws
IOException {
- final ModelFormField.HyperlinkField hyperlinkField =
mock(ModelFormField.HyperlinkField.class);
- when(hyperlinkField.getModelFormField()).thenReturn(modelFormField);
- final String description = "DESCRIPTION";
-
- when(hyperlinkField.getDescription(notNull())).thenReturn(description);
- when(hyperlinkField.getTarget(notNull())).thenReturn("#");
- when(request.getAttribute("descriptionSize")).thenReturn(5);
-
- macroFormRenderer.renderHyperlinkField(appendable, new HashMap<>(),
hyperlinkField);
- assertAndGetMacroString("makeHyperlinkString",
ImmutableMap.of("description", "DESCR…", "title", description));
+ genericSubHyperlinkRenderedVerification();
+ genericTooltipRenderedVerification();
}
@Test
- public void hyperlinkFieldMacroRenderedTruncatedWithTitle() throws
IOException {
- final ModelFormField.HyperlinkField hyperlinkField =
mock(ModelFormField.HyperlinkField.class);
- when(hyperlinkField.getModelFormField()).thenReturn(modelFormField);
- final String description = "DESCRIPTION";
- final String title = "TITLE";
+ public void fieldTitleWithHeaderLinkRendersHyperlinkTitle() throws
IOException {
+ when(modelFormField.getTitle(notNull())).thenReturn("FIELDTITLE");
+ when(modelFormField.getHeaderLink()).thenReturn("/target");
+ when(modelFormField.getModelForm().getName()).thenReturn("FORMNAME");
+ when(renderableFtlFormElementsBuilder.hyperlinkTitle(eq("FORMNAME"),
anyString(), eq(false))).thenReturn(genericMacroCall);
- when(hyperlinkField.getDescription(notNull())).thenReturn(description);
- when(hyperlinkField.getTarget(notNull())).thenReturn("#");
- when(hyperlinkField.getTitle()).thenReturn(title);
- when(request.getAttribute("descriptionSize")).thenReturn(5);
+ macroFormRenderer.renderFieldTitle(appendable, ImmutableMap.of(),
modelFormField);
- macroFormRenderer.renderHyperlinkField(appendable, new HashMap<>(),
hyperlinkField);
- assertAndGetMacroString("makeHyperlinkString",
ImmutableMap.of("description", "DESCR…", "title", description));
+
verify(renderableFtlFormElementsBuilder).hyperlinkMacroCall(nullable(String.class),
anyString(), eq("/target"), isNull(),
+ eq("FIELDTITLE"), eq(""), eq(modelFormField), eq(request),
eq(response), notNull(), eq(""));
+ genericSingleMacroRenderedVerification();
}
@Test
- public void hyperlinkFieldMacroRenderedModalParameters() throws
IOException {
- final ModelFormField.HyperlinkField hyperlinkField =
mock(ModelFormField.HyperlinkField.class);
- when(hyperlinkField.getModelFormField()).thenReturn(modelFormField);
- final String title = "TitleValue";
- final String text = "TextValue";
- final String description = "DescriptionValue";
- final String target = "Encoded Target";
- final String id = "IdValue";
- final String uniqueItemName = "UniqueItemName";
- final String width = "650";
- final String height = "150";
- final String confirmation = "Are you sure ?";
- final String targetWindow = "_blank";
- final Map<String, ConfigXMLReader.RequestMap> requestMapMap = new
HashMap<>();
- final Map<String, String> parameterMap = new HashMap<>();
- parameterMap.put("k1", "v1");
- parameterMap.put("k2", "v2");
-
- when(hyperlinkField.getDescription(notNull())).thenReturn(description);
- when(hyperlinkField.getTarget(notNull())).thenReturn(target);
- when(hyperlinkField.getParameterMap(notNull(), isNull(),
isNull())).thenReturn(parameterMap);
-
when(hyperlinkField.getConfirmation(notNull())).thenReturn(confirmation);
-
when(hyperlinkField.getTargetWindow(notNull())).thenReturn(targetWindow);
- when(request.getAttribute("title")).thenReturn(title);
- when(request.getAttribute("text")).thenReturn(text);
- when(request.getAttribute("requestMapMap")).thenReturn(requestMapMap);
- when(request.getAttribute("id")).thenReturn(id);
-
when(request.getAttribute("uniqueItemName")).thenReturn(uniqueItemName);
- when(request.getAttribute("width")).thenReturn(width);
- when(request.getAttribute("height")).thenReturn(height);
+ public void dropDownSubHyperlinkIsPrecededByASpace() throws IOException {
+ final ModelFormField.DropDownField dropDownField =
mock(ModelFormField.DropDownField.class);
+ final ModelFormField.SubHyperlink subHyperlink =
mock(ModelFormField.SubHyperlink.class);
+ when(dropDownField.getSubHyperlink()).thenReturn(subHyperlink);
+ when(subHyperlink.shouldUse(notNull())).thenReturn(true);
+ when(renderableFtlFormElementsBuilder.dropDownField(notNull(),
eq(dropDownField), anyBoolean())).thenReturn(genericMacroCall);
+
when(renderableFtlFormElementsBuilder.makeHyperlinkString(eq(subHyperlink),
notNull())).thenReturn(genericHyperlinkMacroCall);
+ genericTooltipRenderedExpectation(dropDownField);
- macroFormRenderer.renderHyperlinkField(appendable, new HashMap<>(),
hyperlinkField);
- ImmutableMap<String, Object> result = ImmutableMap.<String,
Object>builder()
- .put("title", title)
- .put("description", description)
- .put("linkUrl", "Encoded%20Target")
- .put("id", id)
- .put("targetParameters",
"\\{\\\"k1\\\":\\\"v1\\\",\\\"k2\\\":\\\"v2\\\",\\\"presentation\\\":\\\"layer\\\"}")
- .put("width", width)
- .put("confirmation", confirmation)
- .put("targetWindow", targetWindow)
- .build();
- assertAndGetMacroString("makeHyperlinkString", result);
+ macroFormRenderer.renderDropDownField(appendable, ImmutableMap.of(),
dropDownField);
+
+ assertThat(appendable.toString(), equalTo(" "));
+ genericSingleMacroRenderedVerification();
+ genericSubHyperlinkRenderedVerification();
+ genericTooltipRenderedVerification();
}
private String assertAndGetMacroString(final String expectedName) {
diff --git
a/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilderTest.java
b/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilderTest.java
index 0bbb861ba3..8389332225 100644
---
a/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilderTest.java
+++
b/framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/macro/RenderableFtlFormElementsBuilderTest.java
@@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableMap;
import org.apache.ofbiz.webapp.control.ConfigXMLReader;
import org.apache.ofbiz.webapp.control.RequestHandler;
import org.apache.ofbiz.widget.content.StaticContentUrlProvider;
+import org.apache.ofbiz.widget.model.FieldInfo;
import org.apache.ofbiz.widget.model.ModelForm;
import org.apache.ofbiz.widget.model.ModelFormField;
import org.apache.ofbiz.widget.model.ModelScreenWidget;
@@ -30,6 +31,7 @@ import org.apache.ofbiz.widget.renderer.VisualTheme;
import
org.apache.ofbiz.widget.renderer.macro.renderable.RenderableFtlMacroCall;
import org.apache.ofbiz.widget.renderer.macro.renderable.RenderableFtl;
import org.apache.ofbiz.widget.renderer.macro.renderable.RenderableFtlNoop;
+import org.apache.ofbiz.widget.renderer.macro.renderable.RenderableFtlString;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -718,4 +720,348 @@ public final class RenderableFtlFormElementsBuilderTest {
assertThat(withTooltip,
MacroCallMatcher.hasNameAndParameters("renderSortField",
MacroCallParameterMatcher.hasNameAndStringValue("tooltip",
"TIP")));
}
+
+ private static RenderableFtlMacroCall macroCall(final RenderableFtl
renderableFtl) {
+ return (RenderableFtlMacroCall) renderableFtl;
+ }
+
+ private ModelFormField columnField(final String name, final int fieldType,
final String titleAreaStyle) {
+ final ModelFormField columnField = mock(ModelFormField.class,
RETURNS_DEEP_STUBS);
+ when(columnField.getName()).thenReturn(name);
+ when(columnField.getFieldInfo().getFieldType()).thenReturn(fieldType);
+ when(columnField.getTitleAreaStyle()).thenReturn(titleAreaStyle);
+ return columnField;
+ }
+
+ @Test
+ public void formOpenSetsTheFormTypeAndTheViewParameters() {
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getType()).thenReturn("single");
+ when(modelForm.getUseRowSubmit()).thenReturn(true);
+
+ final RenderableFtl renderableFtl =
renderableFtlFormElementsBuilder.formOpen(new HashMap<>(), modelForm);
+ assertThat(renderableFtl,
MacroCallMatcher.hasNameAndParameters("renderFormOpen",
+ MacroCallParameterMatcher.hasNameAndStringValue("formType",
"single"),
+
MacroCallParameterMatcher.hasNameAndStringValue("autocomplete", "off"),
+
MacroCallParameterMatcher.hasNameAndStringValue("hasRequiredField", ""),
+
MacroCallParameterMatcher.hasNameAndBooleanValue("useRowSubmit", true),
+ MacroCallParameterMatcher.hasName("viewIndex"),
+ MacroCallParameterMatcher.hasName("viewSize"),
+ MacroCallParameterMatcher.hasName("csrfNameValue")));
+ }
+
+ @Test
+ public void formOpenFlagsTheFormWithARequiredField() {
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getClientAutocompleteFields()).thenReturn(true);
+ final ModelFormField requiredField = mock(ModelFormField.class);
+ when(requiredField.getRequiredField()).thenReturn(true);
+ when(modelForm.getFieldList()).thenReturn(List.of(requiredField));
+
+ final RenderableFtl renderableFtl =
renderableFtlFormElementsBuilder.formOpen(new HashMap<>(), modelForm);
+ assertThat(renderableFtl,
MacroCallMatcher.hasNameAndParameters("renderFormOpen",
+
MacroCallParameterMatcher.hasNameAndStringValue("autocomplete", ""),
+
MacroCallParameterMatcher.hasNameAndStringValue("hasRequiredField", "Y")));
+ }
+
+ @Test
+ public void closingMacrosHaveNoParameters() {
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formClose()).getName(),
equalTo("renderFormClose"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.multiFormClose()).getName(),
equalTo("renderMultiFormClose"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatHeaderOpen()).getName(),
equalTo("renderFormatHeaderOpen"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatHeaderClose()).getName(),
equalTo("renderFormatHeaderClose"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatHeaderRowClose()).getName(),
equalTo("renderFormatHeaderRowClose"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatHeaderRowCellClose()).getName(),
+ equalTo("renderFormatHeaderRowCellClose"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatHeaderRowFormCellClose()).getName(),
+ equalTo("renderFormatHeaderRowFormCellClose"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatItemRowFormCellClose()).getName(),
+ equalTo("renderFormatItemRowFormCellClose"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatFieldRowOpen()).getName(),
equalTo("renderFormatFieldRowOpen"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatFieldRowClose()).getName(),
equalTo("renderFormatFieldRowClose"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatFieldRowTitleCellClose()).getName(),
+ equalTo("renderFormatFieldRowTitleCellClose"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatFieldRowWidgetCellClose()).getName(),
+ equalTo("renderFormatFieldRowWidgetCellClose"));
+
assertThat(macroCall(renderableFtlFormElementsBuilder.formatHeaderRowClose()).getParameters().isEmpty(),
equalTo(true));
+ }
+
+ @Test
+ public void postMultiFormContentIsNothingWhenThereIsNone() {
+ assertThat(renderableFtlFormElementsBuilder.postMultiFormContent(new
HashMap<>()), equalTo(RenderableFtlNoop.INSTANCE));
+
+ final Map<String, Object> context = new HashMap<>();
+ context.put("wholeFormContext", new HashMap<String, Object>());
+
assertThat(renderableFtlFormElementsBuilder.postMultiFormContent(context),
equalTo(RenderableFtlNoop.INSTANCE));
+ }
+
+ @Test
+ public void postMultiFormContentIsWhatTheHiddenFormLinksStored() {
+ final RenderableFtlMacroCall stored =
RenderableFtlMacroCall.builder().name("stored").build();
+ final Map<String, Object> wholeFormContext = new HashMap<>();
+ wholeFormContext.put("postMultiFormRenderableFtl", stored);
+ final Map<String, Object> context = new HashMap<>();
+ context.put("wholeFormContext", wholeFormContext);
+
+
assertThat(renderableFtlFormElementsBuilder.postMultiFormContent(context),
equalTo(stored));
+ }
+
+ @Test
+ public void formatListWrapperOpenCollectsOneStylePerVisibleColumn() {
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getName()).thenReturn("FORMNAME");
+
when(modelForm.getDefaultTableStyle()).thenReturn("STYLE${styleParam}");
+ final List<ModelFormField> fields = List.of(
+ columnField("first", FieldInfo.DISPLAY, "FIRSTSTYLE"),
+ columnField("hidden", FieldInfo.HIDDEN, "HIDDENSTYLE"),
+ columnField("second", FieldInfo.TEXT, "it's a style"),
+ // a second field with the name of the first one only replaces
the style
+ columnField("first", FieldInfo.TEXT, "REPLACEDSTYLE"),
+ columnField("third", FieldInfo.TEXT, null));
+ when(modelForm.getFieldList()).thenReturn(fields);
+
+ final RenderableFtlMacroCall macroCall = macroCall(
+
renderableFtlFormElementsBuilder.formatListWrapperOpen(ImmutableMap.of("styleParam",
"ABCD"), modelForm));
+ assertThat(macroCall,
MacroCallMatcher.hasNameAndParameters("renderFormatListWrapperOpen",
+ MacroCallParameterMatcher.hasNameAndStringValue("formName",
"FORMNAME"),
+ MacroCallParameterMatcher.hasNameAndStringValue("style",
"STYLEABCD")));
+ assertThat(macroCall.getParameters().get("columnStyles"),
equalTo(List.of("REPLACEDSTYLE", "it's a style", "")));
+ }
+
+ @Test
+ public void formatListWrapperOpenWithoutFieldsHasNoColumnStyles() {
+ final ModelForm modelForm = mock(ModelForm.class);
+
+ final RenderableFtlMacroCall macroCall =
macroCall(renderableFtlFormElementsBuilder.formatListWrapperOpen(new
HashMap<>(), modelForm));
+ assertThat(macroCall.getParameters().get("columnStyles"),
equalTo(List.of()));
+ }
+
+ @Test
+ public void emptyFormDataMessageSetsTheMessage() {
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getEmptyFormDataMessage(notNull())).thenReturn("EMPTY
${notEvaluated}");
+
+ assertThat(renderableFtlFormElementsBuilder.emptyFormDataMessage(new
HashMap<>(), modelForm),
+
MacroCallMatcher.hasNameAndParameters("renderEmptyFormDataMessage",
+
MacroCallParameterMatcher.hasNameAndStringValue("message", "EMPTY
${notEvaluated}")));
+ }
+
+ @Test
+ public void formatListWrapperCloseSetsTheFormName() {
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getName()).thenReturn("FORMNAME");
+
+
assertThat(renderableFtlFormElementsBuilder.formatListWrapperClose(modelForm),
+
MacroCallMatcher.hasNameAndParameters("renderFormatListWrapperClose",
+
MacroCallParameterMatcher.hasNameAndStringValue("formName", "FORMNAME")));
+ }
+
+ @Test
+ public void formatHeaderRowOpenExpandsTheStyle() {
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getHeaderRowStyle()).thenReturn("HEADER${styleParam}");
+
+
assertThat(renderableFtlFormElementsBuilder.formatHeaderRowOpen(ImmutableMap.of("styleParam",
"ABCD"), modelForm),
+
MacroCallMatcher.hasNameAndParameters("renderFormatHeaderRowOpen",
+
MacroCallParameterMatcher.hasNameAndStringValue("style", "HEADERABCD")));
+ }
+
+ @Test
+ public void formatHeaderCellsSetStyleAndPositionSpan() {
+ final ModelFormField localModelFormField = mock(ModelFormField.class);
+
when(localModelFormField.getTitleAreaStyle()).thenReturn("TITLEAREASTYLE");
+ when(localModelFormField.getTitleStyle()).thenReturn("TITLESTYLE");
+ final ModelForm modelForm = mock(ModelForm.class);
+
when(modelForm.getFormTitleAreaStyle()).thenReturn("FORMTITLEAREASTYLE");
+
+
assertThat(renderableFtlFormElementsBuilder.formatHeaderRowCellOpen(localModelFormField,
3),
+
MacroCallMatcher.hasNameAndParameters("renderFormatHeaderRowCellOpen",
+
MacroCallParameterMatcher.hasNameAndStringValue("style", "TITLEAREASTYLE"),
+
MacroCallParameterMatcher.hasNameAndIntegerValue("positionSpan", 3)));
+
assertThat(renderableFtlFormElementsBuilder.formatHeaderRowFormCellOpen(modelForm),
+
MacroCallMatcher.hasNameAndParameters("renderFormatHeaderRowFormCellOpen",
+
MacroCallParameterMatcher.hasNameAndStringValue("style",
"FORMTITLEAREASTYLE")));
+
assertThat(renderableFtlFormElementsBuilder.formatHeaderRowFormCellTitleSeparator(localModelFormField,
true),
+
MacroCallMatcher.hasNameAndParameters("renderFormatHeaderRowFormCellTitleSeparator",
+
MacroCallParameterMatcher.hasNameAndStringValue("style", "TITLESTYLE"),
+
MacroCallParameterMatcher.hasNameAndBooleanValue("isLast", true)));
+ }
+
+ @Test
+ public void formatItemRowOpenUsesTheEvenRowStyleForAnEvenIndex() {
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getName()).thenReturn("FORMNAME");
+ when(modelForm.getEvenRowStyle()).thenReturn("EVENSTYLE");
+ when(modelForm.getOddRowStyle()).thenReturn("ODDSTYLE");
+
+
assertThat(renderableFtlFormElementsBuilder.formatItemRowOpen(ImmutableMap.of("itemIndex",
2), modelForm),
+
MacroCallMatcher.hasNameAndParameters("renderFormatItemRowOpen",
+
MacroCallParameterMatcher.hasNameAndStringValue("formName", "FORMNAME"),
+
MacroCallParameterMatcher.hasNameAndIntegerValue("itemIndex", 2),
+
MacroCallParameterMatcher.hasNameAndStringValue("evenRowStyle", "EVENSTYLE"),
+
MacroCallParameterMatcher.hasNameAndStringValue("oddRowStyle", "")));
+ }
+
+ @Test
+ public void formatItemRowOpenUsesTheExpandedOddRowStyleForAnOddIndex() {
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getEvenRowStyle()).thenReturn("EVENSTYLE");
+ when(modelForm.getOddRowStyle()).thenReturn("ODD${styleParam}");
+
+
assertThat(renderableFtlFormElementsBuilder.formatItemRowOpen(ImmutableMap.of("itemIndex",
3, "styleParam", "ABCD"), modelForm),
+
MacroCallMatcher.hasNameAndParameters("renderFormatItemRowOpen",
+
MacroCallParameterMatcher.hasNameAndStringValue("evenRowStyle", ""),
+
MacroCallParameterMatcher.hasNameAndStringValue("oddRowStyle", "ODDABCD")));
+ }
+
+ @Test
+ public void formatItemRowOpenWithoutAnIndexLeavesTheIndexOut() {
+ final ModelForm modelForm = mock(ModelForm.class);
+
+ final RenderableFtlMacroCall macroCall =
macroCall(renderableFtlFormElementsBuilder.formatItemRowOpen(new HashMap<>(),
modelForm));
+ assertThat(macroCall.getParameters(), not(hasKey("itemIndex")));
+ }
+
+ @Test
+ public void formatItemRowCellsSetFieldNameStyleAndPositionSpan() {
+ final ModelFormField localModelFormField = mock(ModelFormField.class);
+ when(localModelFormField.getName()).thenReturn("FIELDNAME");
+ when(localModelFormField.getWidgetAreaStyle()).thenReturn("AREASTYLE");
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getName()).thenReturn("FORMNAME");
+
when(modelForm.getFormTitleAreaStyle()).thenReturn("FORMTITLEAREASTYLE");
+
+
assertThat(renderableFtlFormElementsBuilder.formatItemRowCellOpen(localModelFormField,
2),
+
MacroCallMatcher.hasNameAndParameters("renderFormatItemRowCellOpen",
+
MacroCallParameterMatcher.hasNameAndStringValue("fieldName", "FIELDNAME"),
+
MacroCallParameterMatcher.hasNameAndIntegerValue("positionSpan", 2),
+
MacroCallParameterMatcher.hasNameAndStringValue("style", "AREASTYLE")));
+
assertThat(renderableFtlFormElementsBuilder.formatItemRowCellClose(localModelFormField),
+
MacroCallMatcher.hasNameAndParameters("renderFormatItemRowCellClose",
+
MacroCallParameterMatcher.hasNameAndStringValue("fieldName", "FIELDNAME")));
+
assertThat(renderableFtlFormElementsBuilder.formatItemRowFormCellOpen(modelForm),
+
MacroCallMatcher.hasNameAndParameters("renderFormatItemRowFormCellOpen",
+
MacroCallParameterMatcher.hasNameAndStringValue("style",
"FORMTITLEAREASTYLE")));
+
assertThat(renderableFtlFormElementsBuilder.formatItemRowClose(modelForm),
+
MacroCallMatcher.hasNameAndParameters("renderFormatItemRowClose",
+
MacroCallParameterMatcher.hasNameAndStringValue("formName", "FORMNAME")));
+ }
+
+ @Test
+ public void formatSingleWrapperSetsTheFormNameAndTheExpandedStyle() {
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getName()).thenReturn("FORMNAME");
+
when(modelForm.getDefaultTableStyle()).thenReturn("STYLE${styleParam}");
+
+
assertThat(renderableFtlFormElementsBuilder.formatSingleWrapperOpen(ImmutableMap.of("styleParam",
"ABCD"), modelForm),
+
MacroCallMatcher.hasNameAndParameters("renderFormatSingleWrapperOpen",
+
MacroCallParameterMatcher.hasNameAndStringValue("formName", "FORMNAME"),
+
MacroCallParameterMatcher.hasNameAndStringValue("style", "STYLEABCD")));
+
assertThat(renderableFtlFormElementsBuilder.formatSingleWrapperClose(modelForm),
+
MacroCallMatcher.hasNameAndParameters("renderFormatSingleWrapperClose",
+
MacroCallParameterMatcher.hasNameAndStringValue("formName", "FORMNAME")));
+ }
+
+ @Test
+ public void formatFieldRowCellsSetStyleAndPositionSpan() {
+ final ModelFormField localModelFormField = mock(ModelFormField.class);
+
when(localModelFormField.getTitleAreaStyle()).thenReturn("TITLEAREASTYLE");
+ when(localModelFormField.getWidgetAreaStyle()).thenReturn("AREASTYLE");
+
+
assertThat(renderableFtlFormElementsBuilder.formatFieldRowTitleCellOpen(localModelFormField),
+
MacroCallMatcher.hasNameAndParameters("renderFormatFieldRowTitleCellOpen",
+
MacroCallParameterMatcher.hasNameAndStringValue("style", "TITLEAREASTYLE")));
+
assertThat(renderableFtlFormElementsBuilder.formatFieldRowWidgetCellOpen(localModelFormField,
1),
+
MacroCallMatcher.hasNameAndParameters("renderFormatFieldRowWidgetCellOpen",
+
MacroCallParameterMatcher.hasNameAndIntegerValue("positionSpan", 1),
+
MacroCallParameterMatcher.hasNameAndStringValue("style", "AREASTYLE")));
+ }
+
+ @Test
+ public void boundaryCommentSetsTheTypeAndTheName() {
+ assertThat(renderableFtlFormElementsBuilder.boundaryComment("Begin",
"Form Widget - Form Element", "FORMNAME"),
+ MacroCallMatcher.hasNameAndParameters("formatBoundaryComment",
+
MacroCallParameterMatcher.hasNameAndStringValue("boundaryType", "Begin"),
+
MacroCallParameterMatcher.hasNameAndStringValue("widgetType", "Form Widget -
Form Element"),
+
MacroCallParameterMatcher.hasNameAndStringValue("widgetName", "FORMNAME")));
+ }
+
+ private RenderableFtlMacroCall hyperlink(final String description, final
Map<String, String> parameterMap) {
+ return
macroCall(renderableFtlFormElementsBuilder.makeHyperlinkByType(null, null,
null, "#", parameterMap, description, "", "",
+ modelFormField, request, response, new HashMap<>()));
+ }
+
+ @Test
+ public void
hyperlinkUsesTheTitleOfTheRequestWhenTheDescriptionIsNotTruncated() {
+ when(request.getAttribute("title")).thenReturn("TITLE");
+
+ assertThat(hyperlink("DESCRIPTION", new HashMap<>()),
MacroCallMatcher.hasNameAndParameters("makeHyperlinkString",
+ MacroCallParameterMatcher.hasNameAndStringValue("description",
"DESCRIPTION"),
+ MacroCallParameterMatcher.hasNameAndStringValue("title",
"TITLE")));
+ }
+
+ @Test
+ public void hyperlinkUsesTheDescriptionAsTitleWhenItIsTruncated() {
+ when(request.getAttribute("descriptionSize")).thenReturn(5);
+ when(request.getAttribute("title")).thenReturn("TITLE");
+
+ assertThat(hyperlink("DESCRIPTION", new HashMap<>()),
MacroCallMatcher.hasNameAndParameters("makeHyperlinkString",
+ MacroCallParameterMatcher.hasNameAndStringValue("description",
"DESCR…"),
+ MacroCallParameterMatcher.hasNameAndStringValue("title",
"DESCRIPTION")));
+ }
+
+ @Test
+ public void hyperlinkPassesTheDescriptionAsItIs() {
+ final String description = "say \"hi\" \\ ${1+1} #{2} <#stop>";
+
+ assertThat(hyperlink(description, new HashMap<>()),
MacroCallMatcher.hasNameAndParameters("makeHyperlinkString",
+ MacroCallParameterMatcher.hasNameAndStringValue("description",
description)));
+ }
+
+ @Test
+ public void layeredModalHyperlinkPassesTheParametersAsJsonText() {
+ final Map<String, String> parameterMap = new HashMap<>();
+ parameterMap.put("k1", "v1");
+ parameterMap.put("k2", "v2");
+ when(request.getAttribute("title")).thenReturn("TitleValue");
+ when(request.getAttribute("text")).thenReturn("TextValue");
+ when(request.getAttribute("id")).thenReturn("IdValue");
+
when(request.getAttribute("uniqueItemName")).thenReturn("UniqueItemName");
+ when(request.getAttribute("width")).thenReturn("650");
+ when(request.getAttribute("height")).thenReturn("150");
+
+ assertThat(hyperlink("DescriptionValue", parameterMap),
MacroCallMatcher.hasNameAndParameters("makeHyperlinkString",
+ MacroCallParameterMatcher.hasNameAndStringValue("description",
"DescriptionValue"),
+ MacroCallParameterMatcher.hasNameAndStringValue("title",
"TitleValue"),
+ MacroCallParameterMatcher.hasNameAndStringValue("text",
"TextValue"),
+ MacroCallParameterMatcher.hasNameAndStringValue("id",
"IdValue"),
+
MacroCallParameterMatcher.hasNameAndStringValue("uniqueItemName",
"UniqueItemName"),
+ MacroCallParameterMatcher.hasNameAndStringValue("width",
"650"),
+ MacroCallParameterMatcher.hasNameAndStringValue("height",
"150"),
+
MacroCallParameterMatcher.hasNameAndStringValue("targetParameters",
+
"{\"k1\":\"v1\",\"k2\":\"v2\",\"presentation\":\"layer\"}")));
+ }
+
+ @Test
+ public void hyperlinkWithoutParametersHasNoTargetParameters() {
+ assertThat(hyperlink("DESCRIPTION", new HashMap<>()),
MacroCallMatcher.hasNameAndParameters("makeHyperlinkString",
+
MacroCallParameterMatcher.hasNameAndStringValue("targetParameters", "")));
+ }
+
+ @Test
+ public void
hiddenFormHyperlinkInAMultiFormKeepsTheFormForAfterTheClosingOfTheForm() {
+ final ModelForm modelForm = mock(ModelForm.class);
+ when(modelForm.getType()).thenReturn("multi");
+ when(modelFormField.getModelForm()).thenReturn(modelForm);
+ when(request.getAttribute("title")).thenReturn("");
+ final Map<String, Object> context = new HashMap<>();
+ context.put("wholeFormContext", new HashMap<String, Object>());
+
+ final RenderableFtl link =
renderableFtlFormElementsBuilder.makeHyperlinkByType("hidden-form", "STYLE",
null, "#",
+ new HashMap<>(), "A ${description}", "", "", modelFormField,
request, response, context);
+
+ assertThat(link instanceof RenderableFtlString, equalTo(true));
+ assertThat(((RenderableFtlString) link).getFtlString().contains("A
${description}"), equalTo(true));
+
assertThat(renderableFtlFormElementsBuilder.postMultiFormContent(context)
instanceof RenderableFtlString, equalTo(true));
+ }
}