This is an automated email from the ASF dual-hosted git repository. ddekany pushed a commit to branch 2.3-gae in repository https://gitbox.apache.org/repos/asf/freemarker.git
commit 9e14cb0b55bd2ae266af0b6a702e9f8ef50eb6f8 Author: ddekany <ddek...@apache.org> AuthorDate: Fri Dec 30 23:47:52 2022 +0100 CFormat: Replace two Default23*CFormat classes with a single LegacyCFormat. --- .../freemarker/core/AbstractJSONLikeFormat.java | 3 +- .../freemarker/core/AbstractLegacyCFormat.java | 104 ------------- src/main/java/freemarker/core/Configurable.java | 5 +- .../java/freemarker/core/Default230CFormat.java | 73 --------- .../java/freemarker/core/Default2321CFormat.java | 72 --------- src/main/java/freemarker/core/Environment.java | 25 +-- src/main/java/freemarker/core/JavaCFormat.java | 4 +- src/main/java/freemarker/core/LegacyCFormat.java | 173 +++++++++++++++++++++ src/main/java/freemarker/core/XSCFormat.java | 3 +- .../java/freemarker/core/_StandardCLanguages.java | 3 +- .../java/freemarker/template/Configuration.java | 16 +- src/manual/en_US/book.xml | 80 +++++----- src/test/java/freemarker/core/CustomCFormat.java | 4 +- .../freemarker/template/ConfigurationTest.java | 21 ++- 14 files changed, 253 insertions(+), 333 deletions(-) diff --git a/src/main/java/freemarker/core/AbstractJSONLikeFormat.java b/src/main/java/freemarker/core/AbstractJSONLikeFormat.java index ad6b7349..7f305ff4 100644 --- a/src/main/java/freemarker/core/AbstractJSONLikeFormat.java +++ b/src/main/java/freemarker/core/AbstractJSONLikeFormat.java @@ -37,7 +37,8 @@ public abstract class AbstractJSONLikeFormat extends CFormat { "Infinity", "-Infinity", "NaN", "Infinity", "-Infinity", "NaN"); - private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone(); + private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE + = (DecimalFormat) LegacyCFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.clone(); static { DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols(); symbols.setInfinity("Infinity"); diff --git a/src/main/java/freemarker/core/AbstractLegacyCFormat.java b/src/main/java/freemarker/core/AbstractLegacyCFormat.java deleted file mode 100644 index c564d144..00000000 --- a/src/main/java/freemarker/core/AbstractLegacyCFormat.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 freemarker.core; - -import freemarker.template.TemplateException; -import freemarker.template.TemplateModelException; -import freemarker.template.TemplateNumberModel; -import freemarker.template.utility.StringUtil; -import freemarker.template.utility.StringUtil.JsStringEncCompatibility; -import freemarker.template.utility.StringUtil.JsStringEncQuotation; - -/** - * Super class of {@link CFormat}-s that merely exist to mimic old {@code ?c} behavior for backward compatibility. - * - * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now - * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation. - * The class itself and some members are exposed as they are needed for configuring FreeMarker. - * - * @since 2.3.32 - * @see AbstractJSONLikeFormat - */ -public abstract class AbstractLegacyCFormat extends CFormat { - // Visibility is not "protected" to avoid external implementations while this class is experimental. - AbstractLegacyCFormat() { - } - - @Override - final String formatString(String s, Environment env) throws TemplateException { - return StringUtil.jsStringEnc( - s, JsStringEncCompatibility.JAVA_SCRIPT_OR_JSON, JsStringEncQuotation.QUOTATION_MARK); - } - - @Override - final TemplateNumberFormat getTemplateNumberFormat(Environment env) { - return new LegacyCTemplateNumberFormat(env); - } - - @Override - String getTrueString() { - return "true"; - } - - @Override - String getFalseString() { - return "false"; - } - - @Override - final String getNullString() { - return "null"; - } - - final class LegacyCTemplateNumberFormat extends JavaTemplateNumberFormat { - - public LegacyCTemplateNumberFormat(Environment env) { - super(getLegacyNumberFormat(env), Environment.COMPUTER_FORMAT_STRING); - } - - @Override - public String formatToPlainText(TemplateNumberModel numberModel) throws UnformattableValueException, - TemplateModelException { - Number number = TemplateFormatUtil.getNonNullNumber(numberModel); - return format(number); - } - - @Override - public boolean isLocaleBound() { - return false; - } - - @Override - String format(Number number) throws UnformattableValueException { - if (number instanceof Integer || number instanceof Long) { - // Accelerate these fairly common cases - return number.toString(); - } - return super.format(number); - } - - @Override - public String getDescription() { - return "LegacyC(" + super.getDescription() + ")"; - } - - } - -} diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java index bb6ef998..0e03b220 100644 --- a/src/main/java/freemarker/core/Configurable.java +++ b/src/main/java/freemarker/core/Configurable.java @@ -702,8 +702,7 @@ public class Configurable { * {@code "c"} {@link #setBooleanFormat(String) boolean_format}. * * <p>The default value depends on {@link Configuration#Configuration(Version) incompatible_improvements}. - * If that's 2.3.32 or higher, then it's {@code "JavaScript or JSON"}. For lower it's {@code "default 2.3.31"} or - * {@code "default 2.3.0"}. + * If that's 2.3.32 or higher, then it's {@code "JavaScript or JSON"}, otherwise it's {@code "legacy"}. * * @since 2.3.32 */ @@ -2196,7 +2195,7 @@ public class Configurable { * <br>String value: {@code "default"} (case insensitive) for the default (on {@link Configuration} only), or * one of the predefined values {@code "JavaScript or JSON"}, {@code "JSON"}, * {@code "JavaScript"}, {@code "Java"}, {@code "XS"}, - * {@code "default 2.3.0"}, {@code "default 2.3.21"}, or + * {@code "legacy"}, or * {@code "default"} (only allowed for {@link Configuration} instances) for the default value, * or an <a href="#fm_obe">object builder expression</a> that gives a {@link CFormat} object. * diff --git a/src/main/java/freemarker/core/Default230CFormat.java b/src/main/java/freemarker/core/Default230CFormat.java deleted file mode 100644 index 88749766..00000000 --- a/src/main/java/freemarker/core/Default230CFormat.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 freemarker.core; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.NumberFormat; -import java.util.Locale; - -import freemarker.template.Configuration; -import freemarker.template.Version; - -/** - * Corresponds to the behavior of {@code ?c} if - * {@link Configuration#Configuration(Version) incompatible_improvements} is less than - * {@linkplain Configuration#VERSION_2_3_21 2.3.21}. - * The only good reason for using this is strict backward-compatibility. - * - * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now - * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation. - * The class itself and some members are exposed as they are needed for configuring FreeMarker. - * - * @see Default2321CFormat - * @see JSONCFormat - * - * @since 2.3.32 - */ -public final class Default230CFormat extends AbstractLegacyCFormat { - public static final Default230CFormat INSTANCE = new Default230CFormat(); - public static final String NAME = "default 2.3.0"; - - /** - * "c" number format as it was before Incompatible Improvements 2.3.21. - */ - static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = new DecimalFormat( - "0.################", - new DecimalFormatSymbols(Locale.US)); - static { - LEGACY_NUMBER_FORMAT_PROTOTYPE.setGroupingUsed(false); - LEGACY_NUMBER_FORMAT_PROTOTYPE.setDecimalSeparatorAlwaysShown(false); - } - - private Default230CFormat() { - } - - @Override - NumberFormat getLegacyNumberFormat(Environment env) { - // Note: DecimalFormat-s aren't thread-safe, so you must clone the static field value. - return (NumberFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE.clone(); - } - - @Override - public String getName() { - return NAME; - } -} diff --git a/src/main/java/freemarker/core/Default2321CFormat.java b/src/main/java/freemarker/core/Default2321CFormat.java deleted file mode 100644 index c466769a..00000000 --- a/src/main/java/freemarker/core/Default2321CFormat.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 freemarker.core; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.text.NumberFormat; - -import freemarker.template.Configuration; -import freemarker.template.Version; - -/** - * Corresponds to the behavior of {@code ?c} if - * {@link Configuration#Configuration(Version) incompatible_improvements} is between - * {@linkplain Configuration#VERSION_2_3_21 2.3.21} and {@linkplain Configuration#VERSION_2_3_31 2.3.31}. - * The only good reason for using this is strict backward-compatibility. - * - * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now - * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation. - * The class itself and some members are exposed as they are needed for configuring FreeMarker. - * - * @see Default230CFormat - * @see JSONCFormat - * - * @since 2.3.32 - */ -public final class Default2321CFormat extends AbstractLegacyCFormat { - public static final Default2321CFormat INSTANCE = new Default2321CFormat(); - public static final String NAME = "default 2.3.21"; - - /** - * "c" number format as it was starting from Incompatible Improvements 2.3.21. - */ - private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone(); - static { - DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols(); - symbols.setInfinity("INF"); - symbols.setNaN("NaN"); - LEGACY_NUMBER_FORMAT_PROTOTYPE.setDecimalFormatSymbols(symbols); - } - - private Default2321CFormat() { - } - - @Override - NumberFormat getLegacyNumberFormat(Environment env) { - // Note: DecimalFormat-s aren't thread-safe, so you must clone the static field value. - return (NumberFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE.clone(); - } - - @Override - public String getName() { - return NAME; - } -} diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java index c5be9e17..a56d9ddf 100644 --- a/src/main/java/freemarker/core/Environment.java +++ b/src/main/java/freemarker/core/Environment.java @@ -1679,7 +1679,13 @@ public final class Environment extends Configurable { @Deprecated public NumberFormat getCNumberFormat() { if (cNumberFormat == null) { - cNumberFormat = getCFormatWithPre2331IcIBug().getLegacyNumberFormat(this); + CFormat cFormat = getCFormat(); + if (cFormat == LegacyCFormat.INSTANCE && configuration.getIncompatibleImprovements().intValue() < _VersionInts.V_2_3_31) { + // Emulate old bug + cNumberFormat = ((LegacyCFormat) cFormat).getLegacyNumberFormat(_VersionInts.V_2_3_20); + } else { + cNumberFormat = cFormat.getLegacyNumberFormat(this); + } } return cNumberFormat; } @@ -1705,20 +1711,17 @@ public final class Environment extends Configurable { */ private TemplateNumberFormat getCTemplateNumberFormatWithPre2331IcIBug() { if (cTemplateNumberFormatWithPre2331IcIBug == null) { - cTemplateNumberFormatWithPre2331IcIBug = getCFormatWithPre2331IcIBug().getTemplateNumberFormat(this); + CFormat cFormat = getCFormat(); + if (cFormat == LegacyCFormat.INSTANCE && configuration.getIncompatibleImprovements().intValue() < _VersionInts.V_2_3_31) { + // Emulate old bug + cTemplateNumberFormatWithPre2331IcIBug = ((LegacyCFormat) cFormat).getTemplateNumberFormat(_VersionInts.V_2_3_20); + } else { + cTemplateNumberFormatWithPre2331IcIBug = cFormat.getTemplateNumberFormat(this); + } } return cTemplateNumberFormatWithPre2331IcIBug; } - private CFormat getCFormatWithPre2331IcIBug() { - CFormat cFormat = getCFormat(); - if (cFormat == Default2321CFormat.INSTANCE - && configuration.getIncompatibleImprovements().intValue() < _VersionInts.V_2_3_31) { - return Default230CFormat.INSTANCE; - } - return cFormat; - } - @Override public void setCFormat(CFormat cFormat) { CFormat prevCFormat = getCFormat(); diff --git a/src/main/java/freemarker/core/JavaCFormat.java b/src/main/java/freemarker/core/JavaCFormat.java index 020378e0..64c6feb9 100644 --- a/src/main/java/freemarker/core/JavaCFormat.java +++ b/src/main/java/freemarker/core/JavaCFormat.java @@ -39,7 +39,9 @@ public final class JavaCFormat extends CFormat { "Double.POSITIVE_INFINITY", "Double.NEGATIVE_INFINITY", "Double.NaN", "Float.POSITIVE_INFINITY", "Float.NEGATIVE_INFINITY", "Float.NaN"); - private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone(); + private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE + = (DecimalFormat) LegacyCFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.clone(); + static { DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols(); symbols.setInfinity("Double.POSITIVE_INFINITY"); diff --git a/src/main/java/freemarker/core/LegacyCFormat.java b/src/main/java/freemarker/core/LegacyCFormat.java new file mode 100644 index 00000000..1f3d5886 --- /dev/null +++ b/src/main/java/freemarker/core/LegacyCFormat.java @@ -0,0 +1,173 @@ +/* + * 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 freemarker.core; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.util.Locale; + +import freemarker.template.Configuration; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModelException; +import freemarker.template.TemplateNumberModel; +import freemarker.template.Version; +import freemarker.template._VersionInts; +import freemarker.template.utility.StringUtil; + +/** + * Corresponds to the behavior of {@code ?c} before {@linkplain Configuration#VERSION_2_3_32 2.3.32} (when there + * were no {@link CFormat}-s yet). This only exists for strict backward-compatibility, otherwise avoid this, mostly + * because its number-to-string conversion sometimes do rounding, and infinity and NaN formatting has some glitches. + * This is the default of {@link Configurable#setCFormat(CFormat) c_format} if + * {@link Configuration#Configuration(Version) incompatible_improvements} is less than 2.3.32. + * + * <p>If {@link Configuration#Configuration(Version) incompatible_improvements} is at least + * 2.3.21, then infinity is formatted as {@code INF}, and NaN as + * {@code NaN}. If it's less, then infinity is formatted to the infinity character (U+221E), and NaN to the + * UNICODE replacement character (U+FFFD). But, because of an old bug that we emulate, this only applies to the behavior + * of {@code ?c}/{@code ?cn}, and not to the {@code "c"} and {@code "computer"} + * {@link Configurable#setNumberFormat(String) number_format}. + * The last uses the pre-2.3.21 format before {@link Configuration#Configuration(Version) incompatible_improvements} + * 2.3.31. + * + * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now + * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation. + * The class itself and some members are exposed as they are needed for configuring FreeMarker. + * + * @see JavaScriptOrJSONCFormat + * + * @since 2.3.32 + */ +public final class LegacyCFormat extends CFormat { + public static final LegacyCFormat INSTANCE = new LegacyCFormat(); + public static final String NAME = "legacy"; + + /** + * "c" number format as it was before Incompatible Improvements 2.3.21. + */ + static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0 = new DecimalFormat( + "0.################", + new DecimalFormatSymbols(Locale.US)); + static { + LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.setGroupingUsed(false); + LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.setDecimalSeparatorAlwaysShown(false); + } + + /** + * "c" number format as it was starting from Incompatible Improvements 2.3.21. + */ + private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_21 = (DecimalFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.clone(); + static { + DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_21.getDecimalFormatSymbols(); + symbols.setInfinity("INF"); + symbols.setNaN("NaN"); + LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_21.setDecimalFormatSymbols(symbols); + } + + private LegacyCFormat() { + } + + @Override + final String formatString(String s, Environment env) throws TemplateException { + return StringUtil.jsStringEnc( + s, StringUtil.JsStringEncCompatibility.JAVA_SCRIPT_OR_JSON, StringUtil.JsStringEncQuotation.QUOTATION_MARK); + } + + @Override + final TemplateNumberFormat getTemplateNumberFormat(Environment env) { + return getTemplateNumberFormat(env.getConfiguration().getIncompatibleImprovements().intValue()); + } + + TemplateNumberFormat getTemplateNumberFormat(int iciVersion) { + return new LegacyCTemplateNumberFormat(getLegacyNumberFormat(iciVersion)); + } + + @Override + String getTrueString() { + return "true"; + } + + @Override + String getFalseString() { + return "false"; + } + + @Override + final String getNullString() { + return "null"; + } + + @Override + NumberFormat getLegacyNumberFormat(Environment env) { + // Note: DecimalFormat-s aren't thread-safe, so you must clone the static field value. + return getLegacyNumberFormat(env.getConfiguration().getIncompatibleImprovements().intValue()); + } + + NumberFormat getLegacyNumberFormat(int iciVersion) { + NumberFormat numberFormatPrototype; + if (iciVersion < _VersionInts.V_2_3_21) { + numberFormatPrototype = LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0; + } else { + numberFormatPrototype = LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_21; + } + return (NumberFormat) numberFormatPrototype.clone(); + } + + @Override + public String getName() { + return NAME; + } + + static final class LegacyCTemplateNumberFormat extends JavaTemplateNumberFormat { + + public LegacyCTemplateNumberFormat(NumberFormat numberFormat) { + super(numberFormat, Environment.COMPUTER_FORMAT_STRING); + } + + @Override + public String formatToPlainText(TemplateNumberModel numberModel) throws UnformattableValueException, + TemplateModelException { + Number number = TemplateFormatUtil.getNonNullNumber(numberModel); + return format(number); + } + + @Override + public boolean isLocaleBound() { + return false; + } + + @Override + String format(Number number) throws UnformattableValueException { + if (number instanceof Integer || number instanceof Long) { + // Accelerate these fairly common cases + return number.toString(); + } + return super.format(number); + } + + @Override + public String getDescription() { + return "LegacyC(" + super.getDescription() + ")"; + } + + } + +} diff --git a/src/main/java/freemarker/core/XSCFormat.java b/src/main/java/freemarker/core/XSCFormat.java index 016f8f27..49c4165b 100644 --- a/src/main/java/freemarker/core/XSCFormat.java +++ b/src/main/java/freemarker/core/XSCFormat.java @@ -47,7 +47,8 @@ public final class XSCFormat extends CFormat { "INF", "-INF", "NaN", "INF", "-INF", "NaN"); - private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone(); + private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE + = (DecimalFormat) LegacyCFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.clone(); static { DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols(); symbols.setInfinity("INF"); diff --git a/src/main/java/freemarker/core/_StandardCLanguages.java b/src/main/java/freemarker/core/_StandardCLanguages.java index 9dec5a1b..9a22e7ca 100644 --- a/src/main/java/freemarker/core/_StandardCLanguages.java +++ b/src/main/java/freemarker/core/_StandardCLanguages.java @@ -33,8 +33,7 @@ final class StandardCFormats { addStandardCFormat(JavaScriptCFormat.INSTANCE); addStandardCFormat(JavaCFormat.INSTANCE); addStandardCFormat(XSCFormat.INSTANCE); - addStandardCFormat(Default230CFormat.INSTANCE); - addStandardCFormat(Default2321CFormat.INSTANCE); + addStandardCFormat(LegacyCFormat.INSTANCE); } private static void addStandardCFormat(CFormat cFormat) { diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java index 540294bd..7d4933c4 100644 --- a/src/main/java/freemarker/template/Configuration.java +++ b/src/main/java/freemarker/template/Configuration.java @@ -63,13 +63,12 @@ import freemarker.core.CFormat; import freemarker.core.CSSOutputFormat; import freemarker.core.CombinedMarkupOutputFormat; import freemarker.core.Configurable; -import freemarker.core.Default230CFormat; -import freemarker.core.Default2321CFormat; import freemarker.core.Environment; import freemarker.core.HTMLOutputFormat; import freemarker.core.JSONOutputFormat; import freemarker.core.JavaScriptOrJSONCFormat; import freemarker.core.JavaScriptOutputFormat; +import freemarker.core.LegacyCFormat; import freemarker.core.MarkupOutputFormat; import freemarker.core.OutputFormat; import freemarker.core.ParseException; @@ -959,8 +958,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf * {@code "computer"} {@link Configurable#setNumberFormat(String) number_format}) changes, if the * {@link #setCFormat(CFormat) c_format} setting was left on its default. The default of * {@link #setCFormat(CFormat) c_format} changes to {@link JavaScriptOrJSONCFormat#INSTANCE}, from - * {@link Default2321CFormat#INSTANCE} (or from {@link Default230CFormat#INSTANCE}, depending on the - * previous Incompatible Improvement value), and that's what contains the changes:</p> + * {@link LegacyCFormat#INSTANCE}, and that's what contains the changes:</p> * <ul> * <li><p>Changes affecting non-whole numbers, and whole numbers with over 100 digits: * Formatting is now lossless, so it potentially shows much more decimals. @@ -2512,13 +2510,9 @@ public class Configuration extends Configurable implements Cloneable, ParserConf } static CFormat getDefaultCFormat(Version incompatibleImprovements) { - if (incompatibleImprovements.intValue() >= _VersionInts.V_2_3_32) { - return JavaScriptOrJSONCFormat.INSTANCE; - } - if (incompatibleImprovements.intValue() >= _VersionInts.V_2_3_21) { - return Default2321CFormat.INSTANCE; - } - return Default230CFormat.INSTANCE; + return incompatibleImprovements.intValue() >= _VersionInts.V_2_3_32 + ? JavaScriptOrJSONCFormat.INSTANCE + : LegacyCFormat.INSTANCE; } /** diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml index 06f82070..2f9d3b7d 100644 --- a/src/manual/en_US/book.xml +++ b/src/manual/en_US/book.xml @@ -6120,17 +6120,11 @@ To prove that "s" didn't contain the value in escaped form: </listitem> <listitem> - <para><literal>"default 2.3.0"</literal>: Default for backward - compatibility if the <link + <para><literal>"legacy"</literal>: Default for backward + compatibility when the <link linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal> - setting</link> is less than 2.3.21. Avoid!</para> - </listitem> - - <listitem> - <para><literal>"default 2.3.21"</literal>: Default for backward - compatibility if the <link - linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal> - setting</link> is equal or greater than 2.3.21. Avoid!</para> + setting</link> is less than 2.3.32. Avoid! Can have rounding + losses, and formatting glitches for infinity and NaN.</para> </listitem> </itemizedlist> @@ -13494,12 +13488,11 @@ GreEN mouse <itemizedlist> <listitem> - <para><quote>JSON</quote>, <quote>default 2.3.0</quote>, and - <quote>default 2.3.21</quote>: Gives a JSON string literal, that - is, it will be surrounded with quotation marks - (<literal>"</literal>), and will be escaped using backslash - (<literal>\</literal>) where needed. For the exact escaping - rules see <link linkend="ref_builtin_json_string">the + <para><quote>JSON</quote>, <quote>legacy</quote>: Gives a JSON + string literal, that is, it will be surrounded with quotation + marks (<literal>"</literal>), and will be escaped using + backslash (<literal>\</literal>) where needed. For the exact + escaping rules see <link linkend="ref_builtin_json_string">the <literal>json_string</literal> built-in</link>.</para> </listitem> @@ -16036,18 +16029,18 @@ rif: foo XYr baar</programlisting> <itemizedlist> <listitem> - <para>For all non-deprecated <literal>c_format</literal>-s - that are built into FreeMarker: There's no rounding.</para> + <para>For all that are built into FreeMarker, except + <quote>legacy</quote> <literal>c_format </literal>: There's + no rounding.</para> </listitem> <listitem> - <para>For the deprecated <literal>c_format</literal>-s, - <quote>default 2.3.0</quote>, and <quote>default - 2.3.21</quote>: The numbers are limited to 16 digits after - the decimal dot, so rounding can occur. The these formats - never use exponential form either, so the decimal point - place is fixed. Thus, for example, 1E-17 will be formatted - as <literal>0</literal>. </para> + <para>For the deprecated <literal>c_format</literal>, + <quote>legacy</quote>: The numbers are limited to 16 digits + after the decimal dot, so rounding can occur. The these + formats never use exponential form either, so the decimal + point place is fixed. Thus, for example, 1E-17 will be + formatted as <literal>0</literal>.</para> </listitem> </itemizedlist> </listitem> @@ -16079,14 +16072,19 @@ rif: foo XYr baar</programlisting> <listitem> <para>For <literal>c_format</literal> <quote>XS</quote>, and - also for the deprecated <literal>c_format</literal>, - <quote>default 2.3.21</quote>: <literal>INF</literal>, - <literal>-INF</literal>, and <literal>NaN</literal>.</para> + also if <link + linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal> + setting</link> is at least 2.3.21, for + <literal>c_format</literal>, <quote>legacy</quote>: + <literal>INF</literal>, <literal>-INF</literal>, and + <literal>NaN</literal>.</para> </listitem> <listitem> - <para>For the deprecated <literal>c_format</literal>, - <quote>default 2.3.0</quote>: Gives what + <para>For <literal>c_format</literal> <quote>legacy</quote>, + if <link + linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal> + setting</link> is less than 2.3.21: Gives what <literal>java.text.DecimalFormat</literal> does with US locale, which are <literal>∞</literal>, <literal>-∞</literal>, and <literal>�</literal> (U+FFFD, @@ -16096,10 +16094,9 @@ rif: foo XYr baar</programlisting> </listitem> <listitem> - <para>Exponential form is used by all non-deprecated - <literal>c_format</literal>-s that are built into FreeMarker - (but not by the deprecated <quote>default 2.3.0</quote>, and - <quote>default 2.3.21</quote>):</para> + <para>Exponential form is used by all + <literal>c_format</literal>-s that are built into FreeMarker, + except <quote>legacy</quote>:</para> <itemizedlist> <listitem> @@ -16231,8 +16228,8 @@ rif: foo XYr baar</programlisting> <itemizedlist> <listitem> <para>For <quote>JSON</quote>, <quote>Java</quote>, - <quote>JavaScript</quote>, <quote>default 2.3.0</quote>, - <quote>default 2.3.21</quote>: <literal>null</literal></para> + <quote>JavaScript</quote>, and <quote>legacy</quote>: + <literal>null</literal></para> </listitem> <listitem> @@ -30075,12 +30072,13 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting> <para>If you set the <link linkend="pgui_config_incompatible_improvements_how_to_set"><literal>incompatible_improvements</literal> setting</link> to 2.3.32, the default of - <literal>c_format</literal> changes to - <literal>JSON</literal>, which is a format that most targets - can parse (because we just format simple values, not lists - and maps). With lower + <literal>c_format</literal> changes from + <literal>"legacy"</literal> to <literal>"JavaScript or + JSON"</literal>, which is a format that most targets can + parse (because we just format simple values, not lists and + maps). With lower <literal>incompatible_improvements</literal>, the default - value is a <literal>c_format</literal> that emulates the old + value is <literal>"legacy"</literal> that emulates the old behavior of <literal>?c</literal> (where you can lose numerical prevision, etc.), so it's recommended to set it to something else.</para> diff --git a/src/test/java/freemarker/core/CustomCFormat.java b/src/test/java/freemarker/core/CustomCFormat.java index 86658b0d..9ec224b8 100644 --- a/src/test/java/freemarker/core/CustomCFormat.java +++ b/src/test/java/freemarker/core/CustomCFormat.java @@ -36,8 +36,8 @@ class CustomCFormat extends CFormat { "M:INF", "M:NINF", "M:NaN", "M:INF", "M:NINF", "M:NaN"); - private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = - (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone(); + private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE + = (DecimalFormat) LegacyCFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.clone(); static { DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols(); diff --git a/src/test/java/freemarker/template/ConfigurationTest.java b/src/test/java/freemarker/template/ConfigurationTest.java index 3a6dea5b..756b3fae 100644 --- a/src/test/java/freemarker/template/ConfigurationTest.java +++ b/src/test/java/freemarker/template/ConfigurationTest.java @@ -61,8 +61,6 @@ import freemarker.core.Configurable.SettingValueAssignmentException; import freemarker.core.Configurable.UnknownSettingException; import freemarker.core.ConfigurableTest; import freemarker.core.CustomHTMLOutputFormat; -import freemarker.core.Default230CFormat; -import freemarker.core.Default2321CFormat; import freemarker.core.DefaultTruncateBuiltinAlgorithm; import freemarker.core.DummyOutputFormat; import freemarker.core.Environment; @@ -74,6 +72,7 @@ import freemarker.core.JSONCFormat; import freemarker.core.JavaCFormat; import freemarker.core.JavaScriptCFormat; import freemarker.core.JavaScriptOrJSONCFormat; +import freemarker.core.LegacyCFormat; import freemarker.core.MarkupOutputFormat; import freemarker.core.OptInTemplateClassResolver; import freemarker.core.OutputFormat; @@ -190,13 +189,13 @@ public class ConfigurationTest extends TestCase { assertFalse(((DefaultObjectWrapper) cfg.getObjectWrapper()).getPreferIndexedReadMethod()); cfg = new Configuration(Configuration.VERSION_2_3_0); - assertSame(Default230CFormat.INSTANCE, cfg.getCFormat()); + assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat()); cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_20); - assertSame(Default230CFormat.INSTANCE, cfg.getCFormat()); + assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat()); cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_21); - assertSame(Default2321CFormat.INSTANCE, cfg.getCFormat()); + assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat()); cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_31); - assertSame(Default2321CFormat.INSTANCE, cfg.getCFormat()); + assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat()); cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_32); assertSame(JavaScriptOrJSONCFormat.INSTANCE, cfg.getCFormat()); cfg.setCFormat(JavaScriptOrJSONCFormat.INSTANCE); // Same as default, but explicitly set now @@ -1921,17 +1920,17 @@ public class ConfigurationTest extends TestCase { public void testCFormat() throws TemplateException { Configuration cfg = new Configuration(Configuration.VERSION_2_3_21); - assertSame(Default2321CFormat.INSTANCE, cfg.getCFormat()); - cfg.setSetting(Configuration.C_FORMAT_KEY_SNAKE_CASE, Default230CFormat.NAME); - assertSame(Default230CFormat.INSTANCE, cfg.getCFormat()); + assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat()); + cfg.setSetting(Configuration.C_FORMAT_KEY_SNAKE_CASE, LegacyCFormat.NAME); + assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat()); cfg.setSetting(Configuration.C_FORMAT_KEY_CAMEL_CASE, JSONCFormat.NAME); assertSame(JSONCFormat.INSTANCE, cfg.getCFormat()); cfg.setSetting(Configuration.C_FORMAT_KEY_CAMEL_CASE, "default"); - cfg.setSetting(Configuration.C_FORMAT_KEY_SNAKE_CASE, Default2321CFormat.NAME); + cfg.setSetting(Configuration.C_FORMAT_KEY_SNAKE_CASE, LegacyCFormat.NAME); for (CFormat standardCFormat : new CFormat[] { - Default230CFormat.INSTANCE, Default2321CFormat.INSTANCE, + LegacyCFormat.INSTANCE, JSONCFormat.INSTANCE, JavaScriptCFormat.INSTANCE, JavaCFormat.INSTANCE, XSCFormat.INSTANCE }) {