You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2022/01/13 09:25:28 UTC

[struts] 03/04: WW-5117 Does a conditional evaluation depending on the tag Some tags requires to perform a lazy evaluation which can only happen in ftl template as performing it in the component class is not possible

This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5117-evaluate-dynamic-attributes-cherrypick
in repository https://gitbox.apache.org/repos/asf/struts.git

commit a4a4e9e2625a9545766b83cd70d2e9f9fc24f21b
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Wed Jan 5 20:09:44 2022 +0100

    WW-5117 Does a conditional evaluation depending on the tag
    Some tags requires to perform a lazy evaluation which can only happen in ftl template as performing it in the component class is not possible
---
 .../org/apache/struts2/components/CheckboxList.java     | 16 +++++++++++++---
 .../java/org/apache/struts2/components/ListUIBean.java  |  1 -
 .../main/java/org/apache/struts2/components/Radio.java  | 17 ++++++++++++++---
 .../main/java/org/apache/struts2/components/UIBean.java | 14 ++++++++++++--
 .../src/main/resources/template/simple/checkboxlist.ftl |  8 ++++----
 .../resources/template/simple/dynamic-attributes.ftl    |  6 +++++-
 core/src/main/resources/template/simple/radiomap.ftl    |  5 +++--
 7 files changed, 51 insertions(+), 16 deletions(-)

diff --git a/core/src/main/java/org/apache/struts2/components/CheckboxList.java b/core/src/main/java/org/apache/struts2/components/CheckboxList.java
index e830918..601ce5b 100644
--- a/core/src/main/java/org/apache/struts2/components/CheckboxList.java
+++ b/core/src/main/java/org/apache/struts2/components/CheckboxList.java
@@ -48,7 +48,7 @@ import com.opensymphony.xwork2.util.ValueStack;
         allowDynamicAttributes = true)
 public class CheckboxList extends ListUIBean {
     final public static String TEMPLATE = "checkboxlist";
-    
+
     public CheckboxList(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
         super(stack, request, response);
     }
@@ -56,9 +56,19 @@ public class CheckboxList extends ListUIBean {
     protected String getDefaultTemplate() {
         return TEMPLATE;
     }
-    
+
     public void evaluateExtraParams() {
     	super.evaluateExtraParams();
     }
 
-}
\ No newline at end of file
+    /**
+     * Checkboxlist tag requires lazy evaluation as list of tags is dynamically generated using <s:iterator/>
+     *
+     * @return boolean true by default
+     */
+    @Override
+    protected boolean lazyEvaluation() {
+        return true;
+    }
+
+}
diff --git a/core/src/main/java/org/apache/struts2/components/ListUIBean.java b/core/src/main/java/org/apache/struts2/components/ListUIBean.java
index 26484f2..bfaffe6 100644
--- a/core/src/main/java/org/apache/struts2/components/ListUIBean.java
+++ b/core/src/main/java/org/apache/struts2/components/ListUIBean.java
@@ -195,7 +195,6 @@ public abstract class ListUIBean extends UIBean {
         this.listTitle = listTitle;
     }
 
-
     public void setThrowExceptionOnNullValueAttribute(boolean throwExceptionOnNullValueAttribute) {
         this.throwExceptionOnNullValueAttribute = throwExceptionOnNullValueAttribute;
     }
diff --git a/core/src/main/java/org/apache/struts2/components/Radio.java b/core/src/main/java/org/apache/struts2/components/Radio.java
index 0315cb6..ba5eb47 100644
--- a/core/src/main/java/org/apache/struts2/components/Radio.java
+++ b/core/src/main/java/org/apache/struts2/components/Radio.java
@@ -57,7 +57,7 @@ import javax.servlet.http.HttpServletResponse;
         allowDynamicAttributes = true)
 public class Radio extends ListUIBean {
     final public static String TEMPLATE = "radiomap";
-    
+
     public Radio(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
         super(stack, request, response);
     }
@@ -65,8 +65,19 @@ public class Radio extends ListUIBean {
     protected String getDefaultTemplate() {
         return TEMPLATE;
     }
-    
+
     public void evaluateExtraParams() {
     	super.evaluateExtraParams();
     }
-}
\ No newline at end of file
+
+    /**
+     * Radio tag requires lazy evaluation as list of tags is dynamically generated using <s:iterator/>
+     *
+     * @return boolean true by default
+     */
+    @Override
+    protected boolean lazyEvaluation() {
+        return true;
+    }
+
+}
diff --git a/core/src/main/java/org/apache/struts2/components/UIBean.java b/core/src/main/java/org/apache/struts2/components/UIBean.java
index 9ec23d5..a9b8f50 100644
--- a/core/src/main/java/org/apache/struts2/components/UIBean.java
+++ b/core/src/main/java/org/apache/struts2/components/UIBean.java
@@ -1277,8 +1277,8 @@ public abstract class UIBean extends Component {
             String attrValue = entry.getValue();
 
             if (!isValidTagAttribute(attrName)) {
-                if (ComponentUtils.altSyntax(getStack()) && ComponentUtils.isExpression(attrValue)) {
-                    dynamicAttributes.put(attrName, String.valueOf(ObjectUtils.defaultIfNull(findString(attrValue), attrValue)));
+                if (ComponentUtils.altSyntax(getStack()) && ComponentUtils.containsExpression(attrValue) && !lazyEvaluation()) {
+                    dynamicAttributes.put(attrName, ObjectUtils.defaultIfNull(findString(attrValue), attrValue));
                 } else {
                     dynamicAttributes.put(attrName, attrValue);
                 }
@@ -1302,4 +1302,14 @@ public abstract class UIBean extends Component {
         }
     }
 
+    /**
+     * Used to avoid evaluating attributes in {@link #evaluateParams()} or {@link #evaluateExtraParams()}
+     * as evaluation will happen in tag's template
+     *
+     * @return boolean false if evaluation should be performed in ftl
+     */
+    protected boolean lazyEvaluation() {
+        return false;
+    }
+
 }
diff --git a/core/src/main/resources/template/simple/checkboxlist.ftl b/core/src/main/resources/template/simple/checkboxlist.ftl
index 3fa27f1..87bef66 100644
--- a/core/src/main/resources/template/simple/checkboxlist.ftl
+++ b/core/src/main/resources/template/simple/checkboxlist.ftl
@@ -30,7 +30,7 @@
         <#assign itemKeyStr = stack.findString('top')>
     </#if>
     <#if parameters.listLabelKey??>
-    <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale 
+    <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale
        file for it's localized value.  This is then used as a label -->
         <#assign itemValue = struts.getText(stack.findString(parameters.listLabelKey))/>
     <#elseif parameters.listValue??>
@@ -95,9 +95,10 @@
     <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
     <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
     <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+    <#global evaluate_dynamic_attributes = true/>
     <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
         />
-<label<#rt/> 
+<label<#rt/>
     <#if parameters.id?has_content>
         for="${parameters.id}-${itemCount}"<#rt/>
     <#else>
@@ -106,11 +107,10 @@
         class="checkboxLabel">${itemValue}</label>
 </...@s.iterator>
     <#else>
-    &nbsp;
 </#if>
 <input type="hidden" id="__multiselect_${parameters.id}" name="__multiselect_${parameters.name}"
        value=""<#rt/>
 <#if parameters.disabled!false>
        disabled="disabled"<#rt/>
 </#if>
- />
\ No newline at end of file
+ />
diff --git a/core/src/main/resources/template/simple/dynamic-attributes.ftl b/core/src/main/resources/template/simple/dynamic-attributes.ftl
index 47a9113..7f15aa4 100644
--- a/core/src/main/resources/template/simple/dynamic-attributes.ftl
+++ b/core/src/main/resources/template/simple/dynamic-attributes.ftl
@@ -30,7 +30,11 @@
 <#list aKeys?filter(acceptKey) as aKey><#rt/>
 <#assign keyValue = parameters.dynamicAttributes.get(aKey)/>
 <#if keyValue?is_string>
-  <#assign value = struts.translateVariables(keyValue)!keyValue/>
+  <#if evaluate_dynamic_attributes!false == true>
+    <#assign value = struts.translateVariables(keyValue)!keyValue/><#rt/>
+  <#else>
+    <#assign value = keyValue/><#rt/>
+  </#if>
 <#else>
   <#assign value = keyValue?string/>
 </#if>
diff --git a/core/src/main/resources/template/simple/radiomap.ftl b/core/src/main/resources/template/simple/radiomap.ftl
index 5c37a4b..597300e 100644
--- a/core/src/main/resources/template/simple/radiomap.ftl
+++ b/core/src/main/resources/template/simple/radiomap.ftl
@@ -27,7 +27,7 @@
         <#assign itemKeyStr = stack.findString('top')>
     </#if>
     <#if parameters.listValueKey??>
-        <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale 
+        <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale
              file for it's localized value.  This is then used as a label -->
         <#assign valueKey = stack.findString(parameters.listValueKey)!''/>
         <#if valueKey?has_content>
@@ -94,9 +94,10 @@
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+<#global evaluate_dynamic_attributes = true/>
 <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
 /><#rt/>
 <label for="${parameters.id}${itemKeyStr?replace(".", "_")}"<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl"/>><#rt/>
     ${itemValue}<#t/>
 </label>
-</...@s.iterator>
\ No newline at end of file
+</...@s.iterator>