| /******************************************************************************* |
| * 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.base.util.string.test; |
| |
| import java.math.BigDecimal; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.TimeZone; |
| |
| import junit.framework.TestCase; |
| |
| import org.apache.ofbiz.base.lang.SourceMonitored; |
| import org.apache.ofbiz.base.util.Debug; |
| import org.apache.ofbiz.base.util.string.FlexibleStringExpander; |
| import org.apache.ofbiz.base.conversion.AbstractConverter; |
| import org.apache.ofbiz.base.conversion.ConversionException; |
| import org.apache.ofbiz.base.conversion.Converters; |
| |
| @SourceMonitored |
| public class FlexibleStringExpanderTests extends TestCase { |
| private static final Locale localeToTest = new Locale("en", "US"); |
| private static final Locale badLocale = new Locale("fr"); |
| private static final TimeZone timeZoneToTest = TimeZone.getTimeZone("PST"); |
| private static final TimeZone badTimeZone = TimeZone.getTimeZone("GMT"); |
| |
| private boolean wasVerbose; |
| |
| public FlexibleStringExpanderTests(String name) { |
| super(name); |
| } |
| |
| private static void parserTest(String label, String input, boolean checkCache, String toString) { |
| FlexibleStringExpander fse = FlexibleStringExpander.getInstance(input, false); |
| assertEquals(label + ":toString(no-cache)", toString, fse.toString()); |
| fse = FlexibleStringExpander.getInstance(input, true); |
| assertEquals(label + ":toString(cache)", toString, fse.toString()); |
| if (checkCache) { |
| assertEquals(label + ":same-cache", fse, FlexibleStringExpander.getInstance(input, true)); |
| } |
| } |
| |
| public void testParsing() { |
| parserTest("visible nested replacement", "${'Hello ${var}'}!", true, "${'Hello ${var}'}!"); |
| parserTest("hidden (runtime) nested null callreplacement", "Hello ${${groovy:" + FlexibleStringExpanderTests.class.getName() + ".StaticReturnNull()}}World!", true, "Hello ${${groovy:" + FlexibleStringExpanderTests.class.getName() + ".StaticReturnNull()}}World!"); |
| parserTest("UEL integration(nested): throw Exception", "${${throwException.value}}", true, "${${throwException.value}}"); |
| parserTest("nested-constant-emptynest-emptynest", "${a${}${}", true, "${a${}${}"); |
| parserTest("null", null, true, ""); |
| parserTest("empty", "", true, ""); |
| parserTest("constant-only", "a", false, "a"); |
| parserTest("nested-constant-emptynest-emptynest", "${a${}${}", true, "${a${}${}"); |
| parserTest("groovy", "${groovy:}", true, "${groovy:}"); |
| |
| parserTest("escaped", "\\${}", true, "\\${}"); |
| parserTest("constant-escaped", "a\\${}", true, "a\\${}"); |
| parserTest("escaped-groovy", "\\${groovy:}", true, "\\${groovy:}"); |
| |
| parserTest("missing-}", "${", true, "${"); |
| parserTest("nested-constant-missing-}", "${a${}", true, "${a${}"); |
| parserTest("nested-constant-nested-nested-missing-}", "${a${${}", true, "${a${${}"); |
| parserTest("escaped-missing-}", "\\${", true, "\\${"); |
| parserTest("constant-escaped-missing-}", "a\\${", true, "a\\${"); |
| |
| parserTest("currency", "${?currency(", true, "${?currency("); |
| parserTest("currency", "${?currency()", true, "${?currency()"); |
| parserTest("currency", "${price?currency(", true, "${price?currency("); |
| parserTest("currency", "${price?currency()", true, "${price?currency()"); |
| parserTest("currency", "${?currency(usd", true, "${?currency(usd"); |
| parserTest("currency", "${?currency(usd)", true, "${?currency(usd)"); |
| parserTest("currency", "${price?currency(usd", true, "${price?currency(usd"); |
| parserTest("currency", "${price?currency(usd)", true, "${price?currency(usd)"); |
| parserTest("currency", "${?currency(}", true, "${?currency(}"); |
| parserTest("currency", "${?currency()}", true, "${?currency()}"); |
| parserTest("currency", "${?currency(usd}", true, "${?currency(usd}"); |
| parserTest("currency", "${?currency(usd)}", true, "${?currency(usd)}"); |
| parserTest("currency", "${price?currency(}", true, "${price?currency(}"); |
| parserTest("currency", "${price?currency()}", true, "${price?currency()}"); |
| parserTest("currency", "${price?currency(usd}", true, "${price?currency(usd}"); |
| parserTest("currency", "${price?currency(usd)}", true, "${price?currency(usd)}"); |
| parserTest("currency", "a${price?currency(usd)}b", true, "a${price?currency(usd)}b"); |
| } |
| |
| private static void fseTest(String label, String input, Map<String, Object> context, String compare, boolean isEmpty) { |
| fseTest(label, input, context, null, null, compare, isEmpty); |
| } |
| |
| private static void doFseTest(String label, String input, FlexibleStringExpander fse, Map<String, Object> context, TimeZone timeZone, Locale locale, String compare, Object expand, boolean isEmpty) { |
| assertEquals("isEmpty:" + label, isEmpty, fse.isEmpty()); |
| if (input == null) { |
| assertEquals("getOriginal():" + label, "", fse.getOriginal()); |
| assertEquals("toString():" + label, "", fse.toString()); |
| assertEquals("expandString(null):" + label, "", fse.expandString(null)); |
| assertEquals("expand(null):" + label, null, fse.expand(null)); |
| if (timeZone == null) { |
| assertEquals("expandString(null):" + label, "", fse.expandString(null, locale)); |
| assertEquals("expand(null):" + label, null, fse.expand(null, locale)); |
| } else { |
| assertEquals("expandString(null):" + label, "", fse.expandString(null, timeZone, locale)); |
| assertEquals("expand(null):" + label, null, fse.expand(null, timeZone, locale)); |
| } |
| } else { |
| assertEquals("getOriginal():" + label, input, fse.getOriginal()); |
| assertEquals("toString():" + label, input, fse.toString()); |
| assertEquals("expandString(null):" + label, input, fse.expandString(null)); |
| assertEquals("expand(null):" + label, null, fse.expand(null)); |
| if (timeZone == null) { |
| assertEquals("expandString(null):" + label, input, fse.expandString(null, locale)); |
| assertEquals("expand(null):" + label, null, fse.expand(null, locale)); |
| } else { |
| assertEquals("expandString(null):" + label, input, fse.expandString(null, timeZone, locale)); |
| assertEquals("expand(null):" + label, null, fse.expand(null, timeZone, locale)); |
| } |
| } |
| if (locale == null) { |
| assertEquals(label, compare, fse.expandString(context)); |
| assertEquals("expand:" + label, expand, fse.expand(context)); |
| } else { |
| Locale defaultLocale = Locale.getDefault(); |
| TimeZone defaultTimeZone = TimeZone.getDefault(); |
| try { |
| Locale.setDefault(locale); |
| TimeZone.setDefault(timeZone); |
| assertEquals(label, compare, fse.expandString(context, null, null)); |
| assertEquals(label, expand, fse.expand(context, null, null)); |
| Locale.setDefault(badLocale); |
| TimeZone.setDefault(badTimeZone); |
| assertNotSame(label, compare, fse.expandString(context, null, null)); |
| if (input != null) { |
| assertNotSame(label, expand, fse.expand(context, null, null)); |
| } |
| Map<String, Object> autoUserLogin = new HashMap<String, Object>(); |
| autoUserLogin.put("lastLocale", locale.toString()); |
| autoUserLogin.put("lastTimeZone", timeZone == null ? null : timeZone.getID()); |
| context.put("autoUserLogin", autoUserLogin); |
| assertEquals(label, compare, fse.expandString(context, null, null)); |
| assertEquals(label, expand, fse.expand(context, null, null)); |
| autoUserLogin.put("lastLocale", badLocale.toString()); |
| autoUserLogin.put("lastTimeZone", badTimeZone.getID()); |
| assertNotSame(label, compare, fse.expandString(context, null, null)); |
| if (input != null) { |
| assertNotSame(label, expand, fse.expand(context, null, null)); |
| } |
| context.remove("autoUserLogin"); |
| context.put("locale", locale); |
| context.put("timeZone", timeZone); |
| assertEquals(label, compare, fse.expandString(context, null, null)); |
| assertEquals(label, expand, fse.expand(context, null, null)); |
| context.put("locale", badLocale); |
| context.put("timeZone", badTimeZone); |
| assertNotSame(label, compare, fse.expandString(context, null, null)); |
| if (input != null) { |
| assertNotSame(label, expand, fse.expand(context, null, null)); |
| } |
| context.remove("locale"); |
| context.remove("timeZone"); |
| assertEquals(label, compare, fse.expandString(context, timeZone, locale)); |
| assertEquals(label, expand, fse.expand(context, timeZone, locale)); |
| assertNotSame(label, compare, fse.expandString(context, badTimeZone, badLocale)); |
| if (input != null) { |
| assertNotSame(label, expand, fse.expand(context, badTimeZone, badLocale)); |
| } |
| } finally { |
| Locale.setDefault(defaultLocale); |
| TimeZone.setDefault(defaultTimeZone); |
| } |
| } |
| } |
| |
| private static void fseTest(String label, String input, Map<String, Object> context, TimeZone timeZone, Locale locale, String compare, boolean isEmpty) { |
| fseTest(label, input, context, timeZone, locale, compare, compare, isEmpty); |
| } |
| |
| private static void fseTest(String label, String input, Map<String, Object> context, TimeZone timeZone, Locale locale, String compare, Object expand, boolean isEmpty) { |
| FlexibleStringExpander fse = FlexibleStringExpander.getInstance(input); |
| doFseTest(label, input, fse, context, timeZone, locale, compare, expand, isEmpty); |
| assertEquals("static expandString:" + label, compare, FlexibleStringExpander.expandString(input, context, timeZone, locale)); |
| if (input == null) { |
| assertEquals("static expandString(null, null):" + label, "", FlexibleStringExpander.expandString(input, null)); |
| assertEquals("static expandString(null, null):" + label, "", FlexibleStringExpander.expandString(input, null, locale)); |
| } else { |
| assertEquals("static expandString(input, null):" + label, input, FlexibleStringExpander.expandString(input, null)); |
| assertEquals("static expandString(input, null):" + label, input, FlexibleStringExpander.expandString(input, null, locale)); |
| } |
| if (!fse.isEmpty()) { |
| fse = FlexibleStringExpander.getInstance(input, false); |
| doFseTest(label, input, fse, context, timeZone, locale, compare, expand, isEmpty); |
| } |
| } |
| |
| public static String StaticReturnNull() { |
| return null; |
| } |
| |
| @Override |
| public void setUp() { |
| wasVerbose = Debug.isOn(Debug.VERBOSE); |
| if (getName().equals("testWithVerbosity")) { |
| Debug.set(Debug.VERBOSE, true); |
| } |
| Converters.registerConverter(new SpecialNumberToString()); |
| } |
| |
| @Override |
| public void tearDown() { |
| Debug.set(Debug.VERBOSE, wasVerbose); |
| } |
| |
| public static class ThrowException { |
| public Object getValue() throws Exception { |
| throw new Exception(); |
| } |
| } |
| |
| public static class ThrowNPE { |
| public Object getValue() { |
| throw new NullPointerException(); |
| } |
| } |
| |
| public static class SpecialNumberToString extends AbstractConverter<SpecialNumber, String> { |
| public SpecialNumberToString() { |
| super(SpecialNumber.class, String.class); |
| } |
| |
| public String convert(SpecialNumber obj) throws ConversionException { |
| throw new NullPointerException(); |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| public static class SpecialNumber extends BigDecimal { |
| public SpecialNumber(String value) { |
| super(value); |
| } |
| |
| @Override |
| public String toString() { |
| return getClass().getName(); |
| } |
| } |
| |
| public void testWithVerbosity() { |
| everythingTest(); |
| } |
| |
| public void testQuietly() { |
| everythingTest(); |
| } |
| |
| private void everythingTest() { |
| Map<String, Object> testMap = new HashMap<String, Object>(); |
| testMap.put("date", new java.util.Date(1234567890)); |
| testMap.put("usd", "USD"); |
| testMap.put("amount", new BigDecimal("1234567.89")); |
| testMap.put("blank", ""); |
| testMap.put("exc", "Exception"); |
| testMap.put("nullVar", null); |
| testMap.put("throwException", new ThrowException()); |
| testMap.put("throwNPE", new ThrowNPE()); |
| testMap.put("var", "World"); |
| testMap.put("nested", "Hello ${var}"); |
| testMap.put("testMap", testMap); |
| testMap.put("nestedNull", "Hello ${nullVar}${var}"); |
| testMap.put("specialNumber", new SpecialNumber("1.00")); |
| List<String> testList = new ArrayList<String>(); |
| testList.add("World"); |
| testMap.put("testList", testList); |
| fseTest("null FlexibleStringExpander, null map", null, null, null, null, "", null, true); |
| fseTest("null FlexibleStringExpander", null, testMap, null, null, "", null, true); |
| fseTest("null context", "Hello World!", null, null, null, "Hello World!", null, false); |
| fseTest("plain string", "Hello World!", testMap, null, null, "Hello World!", "Hello World!", false); |
| fseTest("simple replacement", "Hello ${var}!", testMap, "Hello World!", false); |
| fseTest("null FlexibleStringExpander with timeZone/locale", null, testMap, timeZoneToTest, localeToTest, "", null, true); |
| fseTest("empty FlexibleStringExpander", "", testMap, null, null, "", null, true); |
| fseTest("UEL integration(nested): throw Exception", "${${throwException.value}}", testMap, "", false); |
| fseTest("UEL integration: throw Exception", "${throwException.value}", testMap, null, null, "", null, false); |
| fseTest("UEL integration(nested): throw Exception", "${throw${exc}.value}", testMap, "", false); |
| fseTest("UEL integration(nested): throw NPE", "${throwNPE${blank}.value}", testMap, "", false); |
| fseTest("visible nested replacement", "${'Hello ${var}'}!", testMap, "Hello World!", false); |
| fseTest("blank nested replacement", "${'Hel${blank}lo ${var}'}!", testMap, "Hello World!", false); |
| fseTest("UEL integration(nested): null", "${${nu${nullVar}ll}}", testMap, "", false); |
| fseTest("UEL integration(nested): NPE", "${${nullVar.noProp}}", testMap, "", false); |
| fseTest("UEL integration(nested): missing", "${${noL${nullVar}ist[0]}}", testMap, "", false); |
| fseTest("date w/ timezone", "The date is ${date}.", testMap, timeZoneToTest, localeToTest, "The date is 1970-01-14 22:56:07.890.", "The date is 1970-01-14 22:56:07.890.", false); |
| fseTest("just bad", "${foobar", testMap, "${foobar", false); |
| fseTest("constant and bad", "Hello${foobar", testMap, "Hello${foobar", false); |
| fseTest("good and bad", "Hello ${var}${foobar", testMap, "Hello World${foobar", false); |
| fseTest("plain-currency(USD)", "${amount?currency(${usd})}", testMap, null, localeToTest, "$1,234,567.89", false); |
| fseTest("currency(USD)", "The total is ${amount?currency(${usd})}.", testMap, null, localeToTest, "The total is $1,234,567.89.", false); |
| fseTest("currency(USD): null", "The total is ${testMap.missing?currency(${usd})}.", testMap, null, localeToTest, "The total is .", false); |
| fseTest("currency(USD): missing", "The total is ${noList[0]?currency(${usd})}.", testMap, null, localeToTest, "The total is .", false); |
| fseTest("currency(USD): exception", "The total is ${throwException.value?currency(${usd})}.", testMap, null, localeToTest, "The total is .", false); |
| fseTest("null nested", "${${nullVar}}!", testMap, "!", false); |
| fseTest("groovy: script", "${groovy:return \"Hello \" + var + \"!\";}", testMap, "Hello World!", false); |
| fseTest("groovy: null", "${groovy:return null;}!", testMap, "!", false); |
| fseTest("groovy missing property", "${groovy: return noList[0]}", testMap, null, null, "", null, false); |
| fseTest("groovy: throw Exception", "${groovy:return throwException.value;}!", testMap, "!", false); |
| fseTest("groovy: converter exception", "${groovy:return specialNumber;}!", testMap, SpecialNumber.class.getName() + "!", false); |
| fseTest("UEL integration: Map", "Hello ${testMap.var}!", testMap, "Hello World!", false); |
| fseTest("UEL integration: blank", "Hello ${testMap.blank}World!", testMap, "Hello World!", false); |
| fseTest("UEL integration: List", "Hello ${testList[0]}!", testMap, "Hello World!", false); |
| fseTest("UEL integration: null", "${null}", testMap, null, null, "", null, false); |
| fseTest("UEL integration: null dereference", "${nullVar.noProp}", testMap, null, null, "", null, false); |
| fseTest("UEL integration: throw NPE", "${" + FlexibleStringExpanderTests.class.getName() + ".ThrowNPE.noProp}", testMap, null, null, "", null, false); |
| fseTest("UEL integration: missing", "${noList[0]}", testMap, null, null, "", null, false); |
| fseTest("Escaped expression", "This is an \\${escaped} expression", testMap, "This is an ${escaped} expression", false); |
| fseTest("Escaped(groovy) expression", "This is an \\${groovy:escaped} expression", testMap, "This is an ${groovy:escaped} expression", false); |
| |
| fseTest("nested UEL integration(return BigDecimal)", "${a${'moun'}t}", testMap, null, null, "1,234,567.89", testMap.get("amount"), false); |
| fseTest("UEL integration(return BigDecimal)", "${amount}", testMap, null, null, "1,234,567.89", testMap.get("amount"), false); |
| fseTest("groovy: return BigDecimal", "${groovy: return amount;}", testMap, null, null, "1,234,567.89", testMap.get("amount"), false); |
| } |
| } |