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 2021/01/10 11:19:12 UTC
[struts] 01/01: WW-4799 Adding struts.date.format as a conversion
format for DateConverter
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch WW-4799-conversion-format
in repository https://gitbox.apache.org/repos/asf/struts.git
commit d876a2ad930e41dca3a05f8ba252cb16e92aa3d7
Author: Cabasson, Denis - CoSD/DSCo <de...@statcan.gc.ca>
AuthorDate: Mon Jun 12 16:26:02 2017 -0400
WW-4799 Adding struts.date.format as a conversion format for DateConverter
---
.../xwork2/conversion/impl/DateConverter.java | 67 ++++++++++++++++--
.../com/opensymphony/xwork2/StubTextProvider.java | 80 ++++++++++++++++++++++
.../xwork2/conversion/impl/XWorkConverterTest.java | 27 ++++++++
3 files changed, 169 insertions(+), 5 deletions(-)
diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DateConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DateConverter.java
index 749b08b..8337529 100644
--- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DateConverter.java
+++ b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DateConverter.java
@@ -19,6 +19,9 @@
package com.opensymphony.xwork2.conversion.impl;
import org.apache.struts2.conversion.TypeConversionException;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.TextProvider;
+import com.opensymphony.xwork2.util.ValueStack;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
@@ -35,7 +38,7 @@ public class DateConverter extends DefaultTypeConverter {
public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType) {
Date result = null;
- if (value instanceof String && value != null && ((String) value).length() > 0) {
+ if (value instanceof String && ((String) value).length() > 0) {
String sa = (String) value;
Locale locale = getLocale(context);
@@ -66,7 +69,8 @@ public class DateConverter extends DefaultTypeConverter {
}
} else if (java.util.Date.class == toType) {
Date check;
- DateFormat[] dfs = getDateFormats(locale);
+ DateFormat[] dfs = getDateFormats(ActionContext.of(context), locale);
+
for (DateFormat df1 : dfs) {
try {
check = df1.parse(sa);
@@ -87,7 +91,7 @@ public class DateConverter extends DefaultTypeConverter {
result = df.parse(sa);
if (!(Date.class == toType)) {
try {
- Constructor constructor = toType.getConstructor(new Class[]{long.class});
+ Constructor<?> constructor = toType.getConstructor(new Class[]{long.class});
return constructor.newInstance(new Object[]{Long.valueOf(result.getTime())});
} catch (Exception e) {
throw new TypeConversionException("Couldn't create class " + toType + " using default (long) constructor", e);
@@ -102,7 +106,43 @@ public class DateConverter extends DefaultTypeConverter {
return result;
}
- private DateFormat[] getDateFormats(Locale locale) {
+ /**
+ * The user defined global date format,
+ * see {@link org.apache.struts2.components.Date#DATETAG_PROPERTY}
+ *
+ * @param context current ActionContext
+ * @param locale current Locale to convert to
+ * @return defined global format
+ */
+ protected DateFormat getGlobalDateFormat(ActionContext context, Locale locale) {
+ // Add the user provided date format if any
+ SimpleDateFormat globalDateFormat = null;
+
+ final TextProvider tp = findProviderInStack(context.getValueStack());
+
+ if (tp != null) {
+ String globalFormat = tp.getText(org.apache.struts2.components.Date.DATETAG_PROPERTY);
+
+ // if tp.getText can not find the property then the
+ // returned string is the same as input =
+ // DATETAG_PROPERTY
+ if (globalFormat != null
+ && !org.apache.struts2.components.Date.DATETAG_PROPERTY.equals(globalFormat)) {
+ globalDateFormat = new SimpleDateFormat(globalFormat, locale);
+ }
+ }
+ return globalDateFormat;
+ }
+
+ /**
+ * Retrieves the list of date formats to be used when converting dates
+ * @param context the current ActionContext
+ * @param locale the current locale of the action
+ * @return a list of DateFormat to be used for date conversion
+ */
+ private DateFormat[] getDateFormats(ActionContext context, Locale locale) {
+ DateFormat globalDateFormat = getGlobalDateFormat(context, locale);
+
DateFormat dt1 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, locale);
DateFormat dt2 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale);
DateFormat dt3 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale);
@@ -114,7 +154,24 @@ public class DateConverter extends DefaultTypeConverter {
DateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
DateFormat rfc3339dateOnly = new SimpleDateFormat("yyyy-MM-dd");
- return new DateFormat[]{dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly};
+ final DateFormat[] dateFormats;
+
+ if (globalDateFormat == null) {
+ dateFormats = new DateFormat[]{dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly};
+ } else {
+ dateFormats = new DateFormat[]{globalDateFormat, dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly};
+ }
+
+ return dateFormats;
+ }
+
+ private TextProvider findProviderInStack(ValueStack stack) {
+ for (Object o : stack.getRoot()) {
+ if (o instanceof TextProvider) {
+ return (TextProvider) o;
+ }
+ }
+ return null;
}
}
diff --git a/core/src/test/java/com/opensymphony/xwork2/StubTextProvider.java b/core/src/test/java/com/opensymphony/xwork2/StubTextProvider.java
new file mode 100644
index 0000000..4908cb5
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/StubTextProvider.java
@@ -0,0 +1,80 @@
+package com.opensymphony.xwork2;
+
+import com.opensymphony.xwork2.util.ValueStack;
+
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+/**
+ * Created by cabaden on 12/06/2017.
+ */
+public class StubTextProvider implements TextProvider {
+
+ private final Map<String, String> map;
+
+ public StubTextProvider(final Map<String, String> map) {
+ this.map = map;
+ }
+
+ @Override
+ public boolean hasKey(final String key) {
+ return map.containsKey(key);
+ }
+
+ @Override
+ public String getText(final String key) {
+ return map.get(key);
+ }
+
+ @Override
+ public String getText(final String key, final String defaultValue) {
+ final String text = this.getText(key);
+ return text == null? defaultValue : text;
+ }
+
+ @Override
+ public String getText(final String key, final String defaultValue, final String obj) {
+ return this.getText(key, defaultValue);
+ }
+
+ @Override
+ public String getText(final String key, final List<?> args) {
+ return this.getText(key);
+ }
+
+ @Override
+ public String getText(final String key, final String[] args) {
+ return this.getText(key);
+ }
+
+ @Override
+ public String getText(final String key, final String defaultValue, final List<?> args) {
+ return this.getText(key);
+ }
+
+ @Override
+ public String getText(final String key, final String defaultValue, final String[] args) {
+ return this.getText(key);
+ }
+
+ @Override
+ public String getText(final String key, final String defaultValue, final List<?> args, final ValueStack stack) {
+ return this.getText(key, defaultValue);
+ }
+
+ @Override
+ public String getText(final String key, final String defaultValue, final String[] args, final ValueStack stack) {
+ return this.getText(key, defaultValue);
+ }
+
+ @Override
+ public ResourceBundle getTexts(final String bundleName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ResourceBundle getTexts() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
index 3465737..9ca0e0e 100644
--- a/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/conversion/impl/XWorkConverterTest.java
@@ -28,6 +28,8 @@ import com.opensymphony.xwork2.util.Foo;
import com.opensymphony.xwork2.util.FurColor;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
import ognl.OgnlRuntime;
+import ognl.TypeConverter;
+import org.apache.struts2.components.*;
import java.io.IOException;
import java.math.BigDecimal;
@@ -41,6 +43,8 @@ import java.util.*;
import static org.junit.Assert.assertArrayEquals;
+import java.util.Date;
+import java.util.Set;
/**
* @author $Author$
@@ -122,6 +126,29 @@ public class XWorkConverterTest extends XWorkTestCase {
assertEquals(date, dateRfc3339DateOnly);
}
+ public void testDateConversionWithDefault() throws ParseException {
+ Map<String, String> lookupMap = new HashMap<>();
+ TextProvider tp = new StubTextProvider(lookupMap);
+ StubValueStack valueStack = new StubValueStack();
+ valueStack.push(tp);
+ context.put(ActionContext.VALUE_STACK, valueStack);
+
+ String dateToFormat = "2017---06--15";
+ Object unparseableDate = converter.convertValue(context, null, null, null, dateToFormat, Date.class);
+ assertEquals(unparseableDate, com.opensymphony.xwork2.conversion.TypeConverter.NO_CONVERSION_POSSIBLE);
+
+ lookupMap.put(org.apache.struts2.components.Date.DATETAG_PROPERTY, "yyyy---MM--dd");
+
+ SimpleDateFormat format = new SimpleDateFormat("yyyy---MM--dd");
+ Date expectedDate = format.parse(dateToFormat);
+ Object parseableDate = converter.convertValue(context, null, null, null, dateToFormat, Date.class);
+ assertEquals(expectedDate, parseableDate);
+
+ Object standardDate = converter.convertValue(context, null, null, null, "2017-06-15", Date.class);
+ assertEquals(expectedDate, standardDate);
+
+ }
+
public void testFieldErrorMessageAddedForComplexProperty() {
SimpleAction action = new SimpleAction();
action.setBean(new TestBean());