You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by di...@apache.org on 2021/07/23 10:32:04 UTC

[sling-org-apache-sling-scripting-sightly] 02/02: Merge branch 'master' into issue/SLING-10654

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

diru pushed a commit to branch issue/SLING-10654
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly.git

commit 2603a64365291ea722b6e36be96514246da70b0a
Merge: 474697c e6acc53
Author: Dirk Rudolph <dr...@adobe.com>
AuthorDate: Fri Jul 23 12:31:44 2021 +0200

    Merge branch 'master' into issue/SLING-10654

 pom.xml                                            |  37 +++---
 .../engine/extension/FormatFilterExtension.java    |  80 +++++-------
 .../extension/FormatFilterExtensionTest.java       | 145 ++++++++++++++++++++-
 3 files changed, 199 insertions(+), 63 deletions(-)

diff --cc src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/FormatFilterExtension.java
index f7cf405,ff438de..6ec400e
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/FormatFilterExtension.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/FormatFilterExtension.java
@@@ -55,25 -60,6 +62,9 @@@ public class FormatFilterExtension impl
  
      private static final Logger LOG = LoggerFactory.getLogger(FormatFilterExtension.class);
      private static final Pattern PLACEHOLDER_REGEX = Pattern.compile("\\{\\d+}");
 +    private static final Pattern COMPLEX_PLACEHOLDER_REGEX = Pattern.compile("\\{\\d+,[^}]+}");
-     private static final String FORMAT_OPTION = "format";
-     private static final String TYPE_OPTION = "type";
-     private static final String LOCALE_OPTION = "locale";
-     private static final String TIMEZONE_OPTION = "timezone";
- 
-     private static final String DATE_FORMAT_TYPE = "date";
-     private static final String NUMBER_FORMAT_TYPE = "number";
-     private static final String STRING_FORMAT_TYPE = "string";
 +
-     static {
-         try {
-             FormatFilterExtension.class.getClassLoader().loadClass("com.ibm.icu.text.MessageFormat");
-             hasIcuSupport = true;
-         } catch (ClassNotFoundException ex) {
-             LOG.trace("Initialize without ICU support: {}", ex.getMessage(), ex);
-             hasIcuSupport = false;
-         }
-     }
++    private boolean hasIcuSupport = true;
  
      @Override
      public Object call(final RenderContext renderContext, Object... arguments) {
@@@ -100,14 -79,15 +91,15 @@@
              return getNumberFormattedString(runtimeObjectModel, source, options, formatObject);
          }
          if (hasPlaceHolders) {
 -            return getFormattedString(runtimeObjectModel, source, formatObject);
 +            return getFormattedString(runtimeObjectModel, source, options, formatObject, hasComplexPlaceholders);
          }
+ 
          try {
-             // somebody will hate me for this
-             new SimpleDateFormat(source);
+             // try to parse as DateTimeFormatter
+             DateTimeFormatter.ofPattern(source);
              return getDateFormattedString(runtimeObjectModel, source, options, formatObject);
-         } catch (IllegalArgumentException e) {
-             // ignore
+         } catch (IllegalArgumentException ex) {
+             LOG.trace("Not a datetime format: {}", source, ex);
          }
          try {
              // for this too, but such is life
diff --cc src/test/java/org/apache/sling/scripting/sightly/impl/engine/extension/FormatFilterExtensionTest.java
index 63fd1e9,f168883..76f5c63
--- a/src/test/java/org/apache/sling/scripting/sightly/impl/engine/extension/FormatFilterExtensionTest.java
+++ b/src/test/java/org/apache/sling/scripting/sightly/impl/engine/extension/FormatFilterExtensionTest.java
@@@ -18,8 -18,12 +18,13 @@@
   ******************************************************************************/
  package org.apache.sling.scripting.sightly.impl.engine.extension;
  
+ import java.time.LocalDateTime;
+ import java.time.ZoneId;
 +import java.util.Arrays;
+ import java.util.Collections;
+ import java.util.Date;
  import java.util.HashMap;
+ import java.util.Map;
  
  import javax.script.Bindings;
  import javax.script.SimpleBindings;
@@@ -29,9 -34,10 +35,12 @@@ import org.apache.sling.scripting.sight
  import org.apache.sling.scripting.sightly.render.RuntimeObjectModel;
  import org.junit.Test;
  
 +import com.google.common.collect.ImmutableMap;
 +
+ import static org.hamcrest.CoreMatchers.startsWith;
  import static org.junit.Assert.assertEquals;
+ import static org.junit.Assert.assertNull;
+ import static org.junit.Assume.assumeThat;
  
  public class FormatFilterExtensionTest {
  
@@@ -50,30 -56,134 +59,160 @@@
          }
      };
      private final FormatFilterExtension subject = new FormatFilterExtension();
+     private final Date testDate = Date.from(LocalDateTime.of(1918, 12, 1, 0, 0, 0, 0)
+         .atZone(ZoneId.of("UTC"))
+         .toInstant());
+ 
+     @Test
+     public void testDateFormatNull() {
+         assertNull(subject.call(renderContext, "default", new HashMap<String, Object>() {{
+             put(FormatFilterExtension.TYPE_OPTION, "date");
+             put(FormatFilterExtension.FORMAT, null);
+         }}));
+     }
+ 
+     @Test
+     public void testDateFormatNoDateObject() {
+         assertNull(subject.call(renderContext, "yyyy-MM-dd", Collections.singletonMap(FormatFilterExtension.FORMAT, new Object())));
+     }
+ 
+     @Test(expected = SightlyException.class)
+     public void testDateFormatFalseFormat() {
+         assertDate(null, "yT", null, null);
+     }
+ 
+     @Test
+     public void testDateFormatWithUTC() {
+         assertDate("1918-12-01 00:00:00.000Z", "yyyy-MM-dd HH:mm:ss.SSSXXX", "UTC", null);
+     }
+ 
+     @Test
+     public void testDateFormatWithZoneOffset() {
+         assertDate("1918-12-01 02:00:00.000+02:00", "yyyy-MM-dd HH:mm:ss.SSSXXX", "GMT+02:00", null);
+     }
+ 
+     @Test
+     public void testDateFormatWithZoneOffsetRFC822() {
+         assertDate("1918-12-01 02:00:00.000+0200", "yyyy-MM-dd HH:mm:ss.SSSZ", "GMT+02:00", null);
+     }
+ 
+     @Test
+     public void testDateFormatWithZoneName() {
+         assertDate("1918-12-01 02:00:00.000(GMT+02:00)", "yyyy-MM-dd HH:mm:ss.SSS(z)", "GMT+02:00", null);
+     }
+ 
+     /**
+      * When using jdk9 or newer, make sure to set the {@code java.locale.providers = COMPAT,SPI}
+      *
+      * @see <a href="https://docs.oracle.com/javase/9/docs/api/java/util/spi/LocaleServiceProvider.html">LocaleServiceProvider</a>
+      */
+     @Test
+     public void testDateFormatWithEscapedCharacters() {
+         assumeJdk8LocaleData();
+         assertDate("01 December '18 12:00 AM; day in year: 335; week in year: 49",
+             "dd MMMM ''yy hh:mm a; 'day in year': D; 'week in year': w",
+             "UTC",
+             null);
+     }
+ 
+     /**
+      * When using jdk9 or newer, make sure to set the {@code java.locale.providers = COMPAT,SPI}
+      *
+      * @see <a href="https://docs.oracle.com/javase/9/docs/api/java/util/spi/LocaleServiceProvider.html">LocaleServiceProvider</a>
+      */
+     @Test
+     public void testDateFormatWithLocale() {
+         assumeJdk8LocaleData();
+         assertDate("Sonntag, 1 Dez 1918", "EEEE, d MMM y", "UTC", "de");
+     }
+ 
+     /**
+      * When using jdk9 or newer, make sure to set the {@code java.locale.providers = COMPAT,SPI}
+      *
+      * @see <a href="https://docs.oracle.com/javase/9/docs/api/java/util/spi/LocaleServiceProvider.html">LocaleServiceProvider</a>
+      */
+     @Test
+     public void testDateFormatWithFormatStyleShort() {
+         assumeJdk8LocaleData();
+         assertDate("01/12/18", "short", "GMT+02:00", "fr");
+     }
+ 
+     @Test
+     public void testDateFormatWithFormatStyleMedium() {
+         assertDate("1 déc. 1918", "medium", "GMT+02:00", "fr");
+     }
+ 
+     @Test
+     public void testDateFormatWithFormatStyleDefault() {
+         assertDate("1 déc. 1918", "default", "GMT+02:00", "fr");
+     }
+ 
+     @Test
+     public void testDateFormatWithFormatStyleLong() {
+         assertDate("1 décembre 1918", "long", "GMT+02:00", "fr");
+     }
+ 
+     @Test
+     public void testDateFormatWithFormatStyleFull() {
+         assertDate("dimanche 1 décembre 1918", "full", "GMT+02:00", "fr");
+     }
+ 
+     @Test
+     public void testDateFormatMixedWithReservedCharacters() {
+         assertEquals("#1: 1918 {0}", subject.call(renderContext, "#1: yyyy {0}", new HashMap<String, Object>() {{
+             put(FormatFilterExtension.TYPE_OPTION, FormatFilterExtension.DATE_FORMAT_TYPE);
+             put(FormatFilterExtension.FORMAT_OPTION, testDate);
+         }}));
+     }
+ 
+     @Test
+     public void testDateFormatNoNarrowForm() {
+         assertDate("December", "MMMMM", "UTC", "en");
+         assertDate("Sunday", "EEEEE", "UTC", "en");
+         assertDate("Sonntag", "eeeee", "UTC", "de");
+     }
+ 
+     private void assumeJdk8LocaleData() {
+         if(!System.getProperty("java.version").startsWith("1.8")) {
+             assumeThat(System.getProperty("java.locale.providers"), startsWith("COMPAT"));
+         }
+     }
+ 
+     private void assertDate(String expected, String format, String timezone, String locale) {
+         Map<String, Object> options = new HashMap<>();
+         options.put(FormatFilterExtension.FORMAT, testDate);
+         if (timezone != null) {
+             options.put(FormatFilterExtension.TIMEZONE_OPTION, timezone);
+         }
+         if (locale != null) {
+             options.put(FormatFilterExtension.LOCALE_OPTION, locale);
+         }
+         assertEquals(expected, subject.call(renderContext, format, options));
+     }
 -}
 +
 +    @Test
 +    public void testSimpleFormat() {
 +        Object result = subject.call(renderContext,
-             "This {0} a {1} format", ImmutableMap.of("format", Arrays.asList("is", "simple")));
++            "This {0} a {1} format", Collections.singletonMap("format", Arrays.asList("is", "simple")));
 +        assertEquals("This is a simple format", result);
 +    }
 +
 +    @Test
 +    public void testComplexFormatNoSimplePlaceholderWithLocale() {
 +        Object result = subject.call(renderContext,
 +            "This query has {0,plural,zero {# results} one {# result} other {# results}}",
 +            new HashMap<String, Object>() {{
-                 put("format", Arrays.asList(7));
++                put("format", Collections.singletonList(7));
 +                put("locale", "en_US");
 +            }});
 +        assertEquals("This query has 7 results", result);
 +    }
 +
 +    @Test
 +    public void testComplexFormatWithSimplePlaceholderNoLocale() {
 +        Object result = subject.call(renderContext,
 +            "This {0} has {1,plural,zero {# results} one {# result} other {# results}}",
-             ImmutableMap.of("format", Arrays.asList("query", 7)));
++            Collections.singletonMap("format", Arrays.asList("query", 7)));
 +        assertEquals("This query has 7 results", result);
 +    }
 +}