Made TemplateConfiguration immutable, added a TemplateConfiguration.Builder. (This is not the final version of TemplateConfiguration; it will be become cleaner as Template also becomes immutable.)
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/88baea20 Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/88baea20 Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/88baea20 Branch: refs/heads/3 Commit: 88baea20cade54dad8a932124d5ecc691ea088d9 Parents: 23f66eb Author: ddekany <[email protected]> Authored: Wed Apr 5 21:55:34 2017 +0200 Committer: ddekany <[email protected]> Committed: Wed Apr 5 21:55:34 2017 +0200 ---------------------------------------------------------------------- .../core/BuiltInsForMultipleTypes.java | 4 +- .../freemarker/core/BuiltInsForStringsMisc.java | 8 +- .../apache/freemarker/core/Configuration.java | 243 ++-- .../org/apache/freemarker/core/Environment.java | 274 +++++ .../MutableProcessingAndParseConfiguration.java | 48 +- .../core/MutableProcessingConfiguration.java | 346 +++--- .../core/ParserAndProcessingConfiguration.java | 29 + .../freemarker/core/ParserConfiguration.java | 5 +- .../core/ProcessingConfiguration.java | 14 +- .../org/apache/freemarker/core/Template.java | 148 +++ .../freemarker/core/TemplateBooleanFormat.java | 91 ++ .../freemarker/core/TemplateConfiguration.java | 1163 ++++++++++-------- ..._ParserConfigurationWithInheritedFormat.java | 13 +- .../core/model/impl/ClassIntrospector.java | 4 +- .../core/model/impl/DefaultObjectWrapper.java | 4 +- .../DefaultObjectWrapperTCCLSingletonUtil.java | 4 +- .../MergingTemplateConfigurationFactory.java | 40 +- .../templateresolver/TemplateLoadingResult.java | 5 +- .../impl/DefaultTemplateResolver.java | 14 +- .../freemarker/core/util/BuilderBase.java | 34 - .../freemarker/core/util/CommonBuilder.java | 29 + .../freemarker/core/util/FluentBuilder.java | 36 + .../core/util/ProductWrappingBuilder.java | 2 +- src/manual/en_US/FM3-CHANGE-LOG.txt | 1 + .../freemarker/core/ConfigurationTest.java | 6 +- .../apache/freemarker/core/DateFormatTest.java | 7 +- .../IncludeAndImportConfigurableLayersTest.java | 37 +- .../freemarker/core/OutputFormatTest.java | 24 +- .../core/TemplateConfigurationTest.java | 330 ++--- ...igurationWithDefaltTemplateResolverTest.java | 264 ---- ...gurationWithDefaultTemplateResolverTest.java | 264 ++++ .../core/TemplateGetEncodingTest.java | 7 +- .../TemplateConfigurationFactoryTest.java | 27 +- .../core/valueformat/NumberFormatTest.java | 7 +- .../ConfigureOutputFormatExamples.java | 16 +- .../TemplateConfigurationExamples.java | 50 +- .../servlet/FreemarkerServletTest.java | 12 +- 37 files changed, 2217 insertions(+), 1393 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java b/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java index e75ea9e..ab3df64 100644 --- a/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java +++ b/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java @@ -229,11 +229,11 @@ class BuiltInsForMultipleTypes { static class apiBI extends ASTExpBuiltIn { @Override TemplateModel _eval(Environment env) throws TemplateException { - if (!env.isAPIBuiltinEnabled()) { + if (!env.getAPIBuiltinEnabled()) { throw new _MiscTemplateException(this, "Can't use ?api, because the \"", MutableProcessingConfiguration.API_BUILTIN_ENABLED_KEY, "\" configuration setting is false. Think twice before you set it to true though. Especially, " - + "it shouldn't abussed for modifying Map-s and Collection-s."); + + "it shouldn't abused for modifying Map-s and Collection-s."); } final TemplateModel tm = target.eval(env); if (!(tm instanceof TemplateModelWithAPISupport)) { http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java index d0deade..f83cbbb 100644 --- a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java +++ b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java @@ -46,13 +46,13 @@ class BuiltInsForStringsMisc { @Override TemplateModel calculateResult(String s, Environment env) throws TemplateException { final boolean b; - if (s.equals("true")) { + if (s.equals(MiscUtil.C_TRUE)) { b = true; - } else if (s.equals("false")) { + } else if (s.equals(MiscUtil.C_FALSE)) { b = false; - } else if (s.equals(env.getTrueStringValue())) { + } else if (s.equals(env.getTemplateBooleanFormat().getTrueStringValue())) { b = true; - } else if (s.equals(env.getFalseStringValue())) { + } else if (s.equals(env.getTemplateBooleanFormat().getFalseStringValue())) { b = false; } else { throw new _MiscTemplateException(this, env, http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/Configuration.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/Configuration.java b/src/main/java/org/apache/freemarker/core/Configuration.java index 52bfd19..c8e700a 100644 --- a/src/main/java/org/apache/freemarker/core/Configuration.java +++ b/src/main/java/org/apache/freemarker/core/Configuration.java @@ -43,6 +43,7 @@ import java.util.TimeZone; import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; +import org.apache.freemarker.core.arithmetic.ArithmeticEngine; import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper; import org.apache.freemarker.core.model.TemplateHashModelEx; @@ -93,6 +94,8 @@ import org.apache.freemarker.core.util._NullArgumentException; import org.apache.freemarker.core.util._SortedArraySet; import org.apache.freemarker.core.util._StringUtil; import org.apache.freemarker.core.util._UnmodifiableCompositeSet; +import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory; +import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; /** * <b>The main entry point into the FreeMarker API</b>; encapsulates the configuration settings of FreeMarker, @@ -142,7 +145,7 @@ import org.apache.freemarker.core.util._UnmodifiableCompositeSet; * The methods that aren't for modifying settings, like {@link #getTemplate(String)}, are thread-safe. */ public final class Configuration extends MutableProcessingConfiguration<Configuration> - implements Cloneable, ParserConfiguration, ProcessingConfiguration, CustomStateScope { + implements Cloneable, ParserAndProcessingConfiguration, CustomStateScope { private static final String VERSION_PROPERTIES_PATH = "org/apache/freemarker/core/version.properties"; @@ -522,6 +525,16 @@ public final class Configuration extends MutableProcessingConfiguration<Configur return super.getTemplateExceptionHandler(); } + @Override + protected TemplateExceptionHandler getInheritedTemplateExceptionHandler() { + throw new BugException("Missing property value"); + } + + @Override + protected ArithmeticEngine getInheritedArithmeticEngine() { + throw new BugException("Missing property value"); + } + private void recreateTemplateResolverWith( TemplateLoader loader, CacheStorage storage, TemplateLookupStrategy templateLookupStrategy, TemplateNameFormat templateNameFormat, @@ -767,8 +780,8 @@ public final class Configuration extends MutableProcessingConfiguration<Configur /** * Sets a {@link TemplateConfigurationFactory} that will configure individual templates where their settings differ * from those coming from the common {@link Configuration} object. A typical use case for that is specifying the - * {@link TemplateConfiguration#setOutputFormat(OutputFormat) outputFormat} for templates based on their file - * extension or parent directory. + * {@link TemplateConfiguration.Builder#setOutputFormat(OutputFormat) outputFormat} for templates based on their + * file extension or parent directory. * * <p> * Note that the settings suggested by standard file extensions are stronger than that you set here. See @@ -1003,7 +1016,42 @@ public final class Configuration extends MutableProcessingConfiguration<Configur } } } - + + @Override + protected ObjectWrapper getInheritedObjectWrapper() { + throw new BugException("Missing property value"); + } + + @Override + protected Charset getInheritedOutputEncoding() { + throw new BugException("Missing property value"); + } + + @Override + protected Charset getInheritedURLEscapingCharset() { + throw new BugException("Missing property value"); + } + + @Override + protected TemplateClassResolver getInheritedNewBuiltinClassResolver() { + throw new BugException("Missing property value"); + } + + @Override + protected boolean getInheritedAutoFlush() { + throw new BugException("Missing property value"); + } + + @Override + protected boolean getInheritedShowErrorTips() { + throw new BugException("Missing property value"); + } + + @Override + protected boolean getInheritedAPIBuiltinEnabled() { + throw new BugException("Missing property value"); + } + /** * Resets the setting to its default, as if it was never set. This means that when you change the * {@code incompatibe_improvements} setting later, the default will also change as appropriate. Also @@ -1033,6 +1081,11 @@ public final class Configuration extends MutableProcessingConfiguration<Configur localeExplicitlySet = true; } + @Override + protected Locale getInheritedLocale() { + throw new BugException("Missing property value"); + } + /** * Resets the setting to its default, as if it was never set. * @@ -1065,6 +1118,66 @@ public final class Configuration extends MutableProcessingConfiguration<Configur timeZoneExplicitlySet = true; } + @Override + protected TimeZone getInheritedTimeZone() { + throw new BugException("Missing property value"); + } + + @Override + protected TimeZone getInheritedSQLDateAndTimeTimeZone() { + throw new BugException("Missing property value"); + } + + @Override + protected String getInheritedNumberFormat() { + throw new BugException("Missing property value"); + } + + @Override + protected Map<String, TemplateNumberFormatFactory> getInheritedCustomNumberFormats() { + throw new BugException("Missing property value"); + } + + @Override + protected TemplateNumberFormatFactory getInheritedCustomNumberFormat(String name) { + return null; + } + + @Override + protected boolean getInheritedHasCustomFormats() { + return false; + } + + @Override + protected String getInheritedBooleanFormat() { + throw new BugException("Missing property value"); + } + + @Override + protected String getInheritedTimeFormat() { + throw new BugException("Missing property value"); + } + + @Override + protected String getInheritedDateFormat() { + throw new BugException("Missing property value"); + } + + @Override + protected String getInheritedDateTimeFormat() { + throw new BugException("Missing property value"); + } + + @Override + protected Map<String, TemplateDateFormatFactory> getInheritedCustomDateFormats() { + throw new BugException("Missing property value"); + } + + @Override + protected TemplateDateFormatFactory getInheritedCustomDateFormat(String name) { + return null; + } + /** * Resets the setting to its default, as if it was never set. * @@ -1130,6 +1243,31 @@ public final class Configuration extends MutableProcessingConfiguration<Configur logTemplateExceptionsExplicitlySet = true; } + @Override + protected boolean getInheritedLogTemplateExceptions() { + throw new BugException("Missing property value"); + } + + @Override + protected boolean getInheritedLazyImports() { + throw new BugException("Missing property value"); + } + + @Override + protected Boolean getInheritedLazyAutoImports() { + throw new BugException("Missing property value"); + } + + @Override + protected Map<String, String> getInheritedAutoImports() { + throw new BugException("Missing property value"); + } + + @Override + protected List<String> getInheritedAutoIncludes() { + throw new BugException("Missing property value"); + } + /** * Resets the setting to its default, as if it was never set. This means that when you change the * {@code incompatibe_improvements} setting later, the default will also change as appropriate. Also @@ -1260,8 +1398,8 @@ public final class Configuration extends MutableProcessingConfiguration<Configur * Auto-escaping has significance when a value is printed with <code>${...}</code> (or <code>#{...}</code>). If * auto-escaping is on, FreeMarker will assume that the value is plain text (as opposed to markup or some kind of * rich text), so it will escape it according the current output format (see {@link #setOutputFormat(OutputFormat)} - * and {@link TemplateConfiguration#setOutputFormat(OutputFormat)}). If auto-escaping is off, FreeMarker will assume - * that the string value is already in the output format, so it prints it as is to the output. + * and {@link TemplateConfiguration.Builder#setOutputFormat(OutputFormat)}). If auto-escaping is off, FreeMarker + * will assume that the string value is already in the output format, so it prints it as is to the output. * * <p>Further notes on auto-escaping: * <ul> @@ -1286,9 +1424,9 @@ public final class Configuration extends MutableProcessingConfiguration<Configur * One of the {@link #ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}, * {@link #ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY}, and {@link #DISABLE_AUTO_ESCAPING_POLICY} constants. * - * @see TemplateConfiguration#setAutoEscapingPolicy(int) + * @see TemplateConfiguration.Builder#setAutoEscapingPolicy(int) * @see Configuration#setOutputFormat(OutputFormat) - * @see TemplateConfiguration#setOutputFormat(OutputFormat) + * @see TemplateConfiguration.Builder#setOutputFormat(OutputFormat) * * @since 2.3.24 */ @@ -1573,15 +1711,15 @@ public final class Configuration extends MutableProcessingConfiguration<Configur * 2.3.24, it defaults to {@code true}, so the following standard file extensions take their effect: * * <ul> - * <li>{@code ftlh}: Sets {@link TemplateConfiguration#setOutputFormat(OutputFormat) outputFormat} to + * <li>{@code ftlh}: Sets {@link TemplateConfiguration.Builder#setOutputFormat(OutputFormat) outputFormat} to * {@code "HTML"} (i.e., {@link HTMLOutputFormat#INSTANCE}, unless the {@code "HTML"} name is overridden by * {@link #setRegisteredCustomOutputFormats(Collection)}) and - * {@link TemplateConfiguration#setAutoEscapingPolicy(int) autoEscapingPolicy} to + * {@link TemplateConfiguration.Builder#setAutoEscapingPolicy(int) autoEscapingPolicy} to * {@link #ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}. - * <li>{@code ftlx}: Sets {@link TemplateConfiguration#setOutputFormat(OutputFormat) outputFormat} to + * <li>{@code ftlx}: Sets {@link TemplateConfiguration.Builder#setOutputFormat(OutputFormat) outputFormat} to * {@code "XML"} (i.e., {@link XMLOutputFormat#INSTANCE}, unless the {@code "XML"} name is overridden by * {@link #setRegisteredCustomOutputFormats(Collection)}) and - * {@link TemplateConfiguration#setAutoEscapingPolicy(int) autoEscapingPolicy} to + * {@link TemplateConfiguration.Builder#setAutoEscapingPolicy(int) autoEscapingPolicy} to * {@link #ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}. * </ul> * @@ -1647,6 +1785,11 @@ public final class Configuration extends MutableProcessingConfiguration<Configur return templateLanguage; } + @Override + public boolean isTemplateLanguageSet() { + return true; + } + /** * Sets the template language used; this is often overridden for certain file extension with * {@link #setTemplateConfigurations(TemplateConfigurationFactory)}. @@ -2041,7 +2184,7 @@ public final class Configuration extends MutableProcessingConfiguration<Configur * another, so <b>you should always set this setting</b>. If you don't know what charset your should chose, * {@code "UTF-8"} is usually a good choice. * - * @param sourceEncoding The charset, for example {@link StandardCharsets#UTF_8}. + * @param sourceEncoding The charset, for example such as {@link StandardCharsets#UTF_8}. */ public void setSourceEncoding(Charset sourceEncoding) { this.sourceEncoding = sourceEncoding; @@ -2052,10 +2195,13 @@ public final class Configuration extends MutableProcessingConfiguration<Configur return sourceEncoding; } + @Override + public boolean isSourceEncodingSet() { + return true; + } + /** * Resets the setting to its default, as if it was never set. - * - * @since 2.3.26 */ public void unsetSourceEncoding() { if (sourceEncodingExplicitlySet) { @@ -2547,73 +2693,12 @@ public final class Configuration extends MutableProcessingConfiguration<Configur return super.getCorrectedNameForUnknownSetting(name); } - - @Override - protected void doAutoImportsAndIncludes(Environment env) throws TemplateException, IOException { - Template t = env.getMainTemplate(); - doAutoImports(env, t); - doAutoIncludes(env, t); - } - private void doAutoImports(Environment env, Template t) throws IOException, TemplateException { - Map<String, String> envAutoImports = env.isAutoImportsSet() ? env.getAutoImports() : null; - Map<String, String> tAutoImports = t.isAutoImportsSet() ? t.getAutoImports() : null; - - boolean lazyAutoImports = env.getLazyAutoImports() != null ? env.getLazyAutoImports() : env.getLazyImports(); - - for (Map.Entry<String, String> autoImport : getAutoImports().entrySet()) { - String nsVarName = autoImport.getKey(); - if ((tAutoImports == null || !tAutoImports.containsKey(nsVarName)) - && (envAutoImports == null || !envAutoImports.containsKey(nsVarName))) { - env.importLib(autoImport.getValue(), nsVarName, lazyAutoImports); - } - } - if (tAutoImports != null) { - for (Map.Entry<String, String> autoImport : tAutoImports.entrySet()) { - String nsVarName = autoImport.getKey(); - if (envAutoImports == null || !envAutoImports.containsKey(nsVarName)) { - env.importLib(autoImport.getValue(), nsVarName, lazyAutoImports); - } - } - } - if (envAutoImports != null) { - for (Map.Entry<String, String> autoImport : envAutoImports.entrySet()) { - String nsVarName = autoImport.getKey(); - env.importLib(autoImport.getValue(), nsVarName, lazyAutoImports); - } - } + @Override + protected Object getInheritedCustomAttribute(Object name) { + return null; } - - private void doAutoIncludes(Environment env, Template t) throws TemplateException, IOException { - // We can't store autoIncludes in LinkedHashSet-s because setAutoIncludes(List) allows duplicates, - // unfortunately. Yet we have to prevent duplicates among Configuration levels, with the lowest levels having - // priority. So we build some Set-s to do that, but we avoid the most common cases where they aren't needed. - List<String> tAutoIncludes = t.isAutoIncludesSet() ? t.getAutoIncludes() : null; - List<String> envAutoIncludes = env.isAutoIncludesSet() ? env.getAutoIncludes() : null; - - for (String templateName : getAutoIncludes()) { - if ((tAutoIncludes == null || !tAutoIncludes.contains(templateName)) - && (envAutoIncludes == null || !envAutoIncludes.contains(templateName))) { - env.include(getTemplate(templateName, env.getLocale())); - } - } - - if (tAutoIncludes != null) { - for (String templateName : tAutoIncludes) { - if (envAutoIncludes == null || !envAutoIncludes.contains(templateName)) { - env.include(getTemplate(templateName, env.getLocale())); - } - } - } - - if (envAutoIncludes != null) { - for (String templateName : envAutoIncludes) { - env.include(getTemplate(templateName, env.getLocale())); - } - } - } - /** * Returns the FreeMarker version information, most importantly the major.minor.micro version numbers. * http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/Environment.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/Environment.java b/src/main/java/org/apache/freemarker/core/Environment.java index 6733045..5382404 100644 --- a/src/main/java/org/apache/freemarker/core/Environment.java +++ b/src/main/java/org/apache/freemarker/core/Environment.java @@ -42,6 +42,7 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; +import org.apache.freemarker.core.arithmetic.ArithmeticEngine; import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateCollectionModel; import org.apache.freemarker.core.model.TemplateDateModel; @@ -128,6 +129,8 @@ public final class Environment extends MutableProcessingConfiguration<Environmen private Map<String, TemplateNumberFormat> cachedTemplateNumberFormats; private Map<CustomStateKey, Object> customStateMap; + private TemplateBooleanFormat cachedTemplateBooleanFormat; + /** * Stores the date/time/date-time formatters that are used when no format is explicitly given at the place of * formatting. That is, in situations like ${lastModified} or even ${lastModified?date}, but not in situations like @@ -321,6 +324,75 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } /** + * Executes the auto-imports and auto-includes for the main template of this environment. + * This is not meant to be called or overridden by code outside of FreeMarker. + */ + private void doAutoImportsAndIncludes(Environment env) throws TemplateException, IOException { + Template t = getMainTemplate(); + doAutoImports(t); + doAutoIncludes(t); + } + + private void doAutoImports(Template t) throws IOException, TemplateException { + Map<String, String> envAutoImports = isAutoImportsSet() ? getAutoImports() : null; + Map<String, String> tAutoImports = t.isAutoImportsSet() ? t.getAutoImports() : null; + + boolean lazyAutoImports = getLazyAutoImports() != null ? getLazyAutoImports() : getLazyImports(); + + for (Map.Entry<String, String> autoImport : configuration.getAutoImports().entrySet()) { + String nsVarName = autoImport.getKey(); + if ((tAutoImports == null || !tAutoImports.containsKey(nsVarName)) + && (envAutoImports == null || !envAutoImports.containsKey(nsVarName))) { + importLib(autoImport.getValue(), nsVarName, lazyAutoImports); + } + } + if (tAutoImports != null) { + for (Map.Entry<String, String> autoImport : tAutoImports.entrySet()) { + String nsVarName = autoImport.getKey(); + if (envAutoImports == null || !envAutoImports.containsKey(nsVarName)) { + importLib(autoImport.getValue(), nsVarName, lazyAutoImports); + } + } + } + if (envAutoImports != null) { + for (Map.Entry<String, String> autoImport : envAutoImports.entrySet()) { + String nsVarName = autoImport.getKey(); + importLib(autoImport.getValue(), nsVarName, lazyAutoImports); + } + } + } + + private void doAutoIncludes(Template t) throws TemplateException, IOException { + // We can't store autoIncludes in LinkedHashSet-s because setAutoIncludes(List) allows duplicates, + // unfortunately. Yet we have to prevent duplicates among Configuration levels, with the lowest levels having + // priority. So we build some Set-s to do that, but we avoid the most common cases where they aren't needed. + + List<String> tAutoIncludes = t.isAutoIncludesSet() ? t.getAutoIncludes() : null; + List<String> envAutoIncludes = isAutoIncludesSet() ? getAutoIncludes() : null; + + for (String templateName : configuration.getAutoIncludes()) { + if ((tAutoIncludes == null || !tAutoIncludes.contains(templateName)) + && (envAutoIncludes == null || !envAutoIncludes.contains(templateName))) { + include(configuration.getTemplate(templateName, getLocale())); + } + } + + if (tAutoIncludes != null) { + for (String templateName : tAutoIncludes) { + if (envAutoIncludes == null || !envAutoIncludes.contains(templateName)) { + include(configuration.getTemplate(templateName, getLocale())); + } + } + } + + if (envAutoIncludes != null) { + for (String templateName : envAutoIncludes) { + include(configuration.getTemplate(templateName, getLocale())); + } + } + } + + /** * "Visit" the template element. */ void visit(ASTElement element) throws IOException, TemplateException { @@ -849,6 +921,21 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override + protected TemplateExceptionHandler getInheritedTemplateExceptionHandler() { + return getParent().getTemplateExceptionHandler(); + } + + @Override + protected ArithmeticEngine getInheritedArithmeticEngine() { + return getParent().getArithmeticEngine(); + } + + @Override + protected ObjectWrapper getInheritedObjectWrapper() { + return getParent().getObjectWrapper(); + } + + @Override public void setLocale(Locale locale) { Locale prevLocale = getLocale(); super.setLocale(locale); @@ -874,6 +961,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override + protected Locale getInheritedLocale() { + return getParent().getLocale(); + } + + @Override public void setTimeZone(TimeZone timeZone) { TimeZone prevTimeZone = getTimeZone(); super.setTimeZone(timeZone); @@ -898,6 +990,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override + protected TimeZone getInheritedTimeZone() { + return getParent().getTimeZone(); + } + + @Override public void setSQLDateAndTimeTimeZone(TimeZone timeZone) { TimeZone prevTimeZone = getSQLDateAndTimeTimeZone(); super.setSQLDateAndTimeTimeZone(timeZone); @@ -921,6 +1018,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } } + @Override + protected TimeZone getInheritedSQLDateAndTimeTimeZone() { + return getParent().getSQLDateAndTimeTimeZone(); + } + // Replace with Objects.equals in Java 7 private static boolean nullSafeEquals(Object o1, Object o2) { if (o1 == o2) return true; @@ -947,6 +1049,61 @@ public final class Environment extends MutableProcessingConfiguration<Environmen super.setURLEscapingCharset(urlEscapingCharset); } + @Override + protected Charset getInheritedURLEscapingCharset() { + return getParent().getURLEscapingCharset(); + } + + @Override + protected TemplateClassResolver getInheritedNewBuiltinClassResolver() { + return getParent().getNewBuiltinClassResolver(); + } + + @Override + protected boolean getInheritedAutoFlush() { + return getParent().getAutoFlush(); + } + + @Override + protected boolean getInheritedShowErrorTips() { + return getParent().getShowErrorTips(); + } + + @Override + protected boolean getInheritedAPIBuiltinEnabled() { + return getParent().getAPIBuiltinEnabled(); + } + + @Override + protected boolean getInheritedLogTemplateExceptions() { + return getParent().getLogTemplateExceptions(); + } + + @Override + protected boolean getInheritedLazyImports() { + return getParent().getLazyImports(); + } + + @Override + protected Boolean getInheritedLazyAutoImports() { + return getParent().getLazyAutoImports(); + } + + @Override + protected Map<String, String> getInheritedAutoImports() { + return getParent().getAutoImports(); + } + + @Override + protected List<String> getInheritedAutoIncludes() { + return getParent().getAutoIncludes(); + } + + @Override + protected Object getInheritedCustomAttribute(Object name) { + return getParent().getCustomAttribute(name); + } + /* * Note that altough it's not allowed to set this setting with the <tt>setting</tt> directive, it still must be * allowed to set it from Java code while the template executes, since some frameworks allow templates to actually @@ -958,6 +1115,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen super.setOutputEncoding(outputEncoding); } + @Override + protected Charset getInheritedOutputEncoding() { + return getParent().getOutputEncoding(); + } + /** * Returns the name of the charset that should be used for URL encoding. This will be <code>null</code> if the * information is not available. The function caches the return value, so it's quick to call it repeatedly. @@ -1056,6 +1218,93 @@ public final class Environment extends MutableProcessingConfiguration<Environmen cachedTemplateNumberFormat = null; } + @Override + protected String getInheritedNumberFormat() { + return getParent().getNumberFormat(); + } + + @Override + protected Map<String, TemplateNumberFormatFactory> getInheritedCustomNumberFormats() { + return getParent().getCustomNumberFormats(); + } + + @Override + protected TemplateNumberFormatFactory getInheritedCustomNumberFormat(String name) { + return getParent().getCustomNumberFormat(name); + } + + @Override + protected boolean getInheritedHasCustomFormats() { + return getParent().hasCustomFormats(); + } + + @Override + protected String getInheritedBooleanFormat() { + return getParent().getBooleanFormat(); + } + + String formatBoolean(boolean value, boolean fallbackToTrueFalse) throws TemplateException { + TemplateBooleanFormat templateBooleanFormat = getTemplateBooleanFormat(); + if (value) { + String s = templateBooleanFormat.getTrueStringValue(); + if (s == null) { + if (fallbackToTrueFalse) { + return MiscUtil.C_TRUE; + } else { + throw new _MiscTemplateException(getNullBooleanFormatErrorDescription()); + } + } else { + return s; + } + } else { + String s = templateBooleanFormat.getFalseStringValue(); + if (s == null) { + if (fallbackToTrueFalse) { + return MiscUtil.C_FALSE; + } else { + throw new _MiscTemplateException(getNullBooleanFormatErrorDescription()); + } + } else { + return s; + } + } + } + + TemplateBooleanFormat getTemplateBooleanFormat() { + TemplateBooleanFormat format = cachedTemplateBooleanFormat; + if (format == null) { + format = TemplateBooleanFormat.getInstance(getBooleanFormat()); + cachedTemplateBooleanFormat = format; + } + return format; + } + + @Override + public void setBooleanFormat(String booleanFormat) { + String previousFormat = getBooleanFormat(); + super.setBooleanFormat(booleanFormat); + if (!booleanFormat.equals(previousFormat)) { + cachedTemplateBooleanFormat = null; + } + } + + private _ErrorDescriptionBuilder getNullBooleanFormatErrorDescription() { + return new _ErrorDescriptionBuilder( + "Can't convert boolean to string automatically, because the \"", BOOLEAN_FORMAT_KEY ,"\" setting was ", + new _DelayedJQuote(getBooleanFormat()), + (getBooleanFormat().equals(TemplateBooleanFormat.C_TRUE_FALSE) + ? ", which is the legacy default computer-language format, and hence isn't accepted." + : ".") + ).tips( + "If you just want \"true\"/\"false\" result as you are generting computer-language output, " + + "use \"?c\", like ${myBool?c}.", + "You can write myBool?string('yes', 'no') and like to specify boolean formatting in place.", + new Object[] { + "If you need the same two values on most places, the programmers should set the \"", + BOOLEAN_FORMAT_KEY ,"\" setting to something like \"yes,no\"." } + ); + } + /** * Format number with the default number format. * @@ -1285,6 +1534,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override + protected String getInheritedTimeFormat() { + return getParent().getTimeFormat(); + } + + @Override public void setDateFormat(String dateFormat) { String prevDateFormat = getDateFormat(); super.setDateFormat(dateFormat); @@ -1298,6 +1552,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override + protected String getInheritedDateFormat() { + return getParent().getDateFormat(); + } + + @Override public void setDateTimeFormat(String dateTimeFormat) { String prevDateTimeFormat = getDateTimeFormat(); super.setDateTimeFormat(dateTimeFormat); @@ -1310,6 +1569,21 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } } + @Override + protected String getInheritedDateTimeFormat() { + return getParent().getDateTimeFormat(); + } + + @Override + protected Map<String, TemplateDateFormatFactory> getInheritedCustomDateFormats() { + return getParent().getCustomDateFormats(); + } + + @Override + protected TemplateDateFormatFactory getInheritedCustomDateFormat(String name) { + return getParent().getCustomDateFormat(name); + } + public Configuration getConfiguration() { return configuration; } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java b/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java index 03cfb95..aaac98d 100644 --- a/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java +++ b/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java @@ -30,7 +30,7 @@ import org.apache.freemarker.core.util._NullArgumentException; public abstract class MutableProcessingAndParseConfiguration< SelfT extends MutableProcessingAndParseConfiguration<SelfT>> extends MutableProcessingConfiguration<SelfT> - implements ParserConfiguration { + implements ParserAndProcessingConfiguration { private TemplateLanguage templateLanguage; private Integer tagSyntax; @@ -63,10 +63,10 @@ public abstract class MutableProcessingAndParseConfiguration< */ @Override public int getTagSyntax() { - return tagSyntax != null ? tagSyntax : getDefaultTagSyntax(); + return tagSyntax != null ? tagSyntax : getInheritedTagSyntax(); } - protected abstract int getDefaultTagSyntax(); + protected abstract int getInheritedTagSyntax(); @Override public boolean isTagSyntaxSet() { @@ -78,10 +78,10 @@ public abstract class MutableProcessingAndParseConfiguration< */ @Override public TemplateLanguage getTemplateLanguage() { - return templateLanguage != null ? templateLanguage : getDefaultTemplateLanguage(); + return isTemplateLanguageSet() ? templateLanguage : getInheritedTemplateLanguage(); } - protected abstract TemplateLanguage getDefaultTemplateLanguage(); + protected abstract TemplateLanguage getInheritedTemplateLanguage(); /** * See {@link Configuration#setTemplateLanguage(TemplateLanguage)} @@ -108,11 +108,11 @@ public abstract class MutableProcessingAndParseConfiguration< */ @Override public int getNamingConvention() { - return namingConvention != null ? namingConvention - : getDefaultNamingConvention(); + return isNamingConventionSet() ? namingConvention + : getInheritedNamingConvention(); } - protected abstract int getDefaultNamingConvention(); + protected abstract int getInheritedNamingConvention(); /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. @@ -134,11 +134,11 @@ public abstract class MutableProcessingAndParseConfiguration< */ @Override public boolean getWhitespaceStripping() { - return whitespaceStripping != null ? whitespaceStripping.booleanValue() - : getDefaultWhitespaceStripping(); + return isWhitespaceStrippingSet() ? whitespaceStripping.booleanValue() + : getInheritedWhitespaceStripping(); } - protected abstract boolean getDefaultWhitespaceStripping(); + protected abstract boolean getInheritedWhitespaceStripping(); /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. @@ -162,11 +162,11 @@ public abstract class MutableProcessingAndParseConfiguration< */ @Override public int getAutoEscapingPolicy() { - return autoEscapingPolicy != null ? autoEscapingPolicy.intValue() - : getDefaultAutoEscapingPolicy(); + return isAutoEscapingPolicySet() ? autoEscapingPolicy.intValue() + : getInheritedAutoEscapingPolicy(); } - protected abstract int getDefaultAutoEscapingPolicy(); + protected abstract int getInheritedAutoEscapingPolicy(); /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. @@ -189,10 +189,10 @@ public abstract class MutableProcessingAndParseConfiguration< */ @Override public OutputFormat getOutputFormat() { - return outputFormat != null ? outputFormat : getDefaultOutputFormat(); + return isOutputFormatSet() ? outputFormat : getInheritedOutputFormat(); } - protected abstract OutputFormat getDefaultOutputFormat(); + protected abstract OutputFormat getInheritedOutputFormat(); /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. @@ -214,11 +214,11 @@ public abstract class MutableProcessingAndParseConfiguration< */ @Override public boolean getRecognizeStandardFileExtensions() { - return recognizeStandardFileExtensions != null ? recognizeStandardFileExtensions.booleanValue() - : getDefaultRecognizeStandardFileExtensions(); + return isRecognizeStandardFileExtensionsSet() ? recognizeStandardFileExtensions.booleanValue() + : getInheritedRecognizeStandardFileExtensions(); } - protected abstract boolean getDefaultRecognizeStandardFileExtensions(); + protected abstract boolean getInheritedRecognizeStandardFileExtensions(); /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. @@ -228,11 +228,12 @@ public abstract class MutableProcessingAndParseConfiguration< return recognizeStandardFileExtensions != null; } + @Override public Charset getSourceEncoding() { - return sourceEncoding != null ? sourceEncoding : getDefaultSourceEncoding(); + return isSourceEncodingSet() ? sourceEncoding : getInheritedSourceEncoding(); } - protected abstract Charset getDefaultSourceEncoding(); + protected abstract Charset getInheritedSourceEncoding(); /** * The charset to be used when reading the template "file" that the {@link TemplateLoader} returns as binary @@ -263,11 +264,10 @@ public abstract class MutableProcessingAndParseConfiguration< */ @Override public int getTabSize() { - return tabSize != null ? tabSize.intValue() - : getDefaultTabSize(); + return isTabSizeSet() ? tabSize.intValue() : getInheritedTabSize(); } - protected abstract int getDefaultTabSize(); + protected abstract int getInheritedTabSize(); /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java index a1e756a..305194d 100644 --- a/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java +++ b/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java @@ -19,7 +19,6 @@ package org.apache.freemarker.core; -import java.io.IOException; import java.io.Writer; import java.nio.charset.Charset; import java.text.NumberFormat; @@ -35,7 +34,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import java.util.TimeZone; @@ -91,8 +89,6 @@ import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; */ public abstract class MutableProcessingConfiguration<SelfT extends MutableProcessingConfiguration<SelfT>> implements ProcessingConfiguration { - static final String C_TRUE_FALSE = "true,false"; - public static final String NULL_VALUE = "null"; public static final String DEFAULT_VALUE = "default"; public static final String JVM_DEFAULT_VALUE = "JVM default"; @@ -321,20 +317,17 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces URL_ESCAPING_CHARSET_KEY_CAMEL_CASE }; - private MutableProcessingConfiguration parent; - private Map<Object, Object> customAttributes; - + private ProcessingConfiguration parent; + private Locale locale; private String numberFormat; private String timeFormat; private String dateFormat; private String dateTimeFormat; private TimeZone timeZone; - private TimeZone sqlDataAndTimeTimeZone; - private boolean sqlDataAndTimeTimeZoneSet; + private TimeZone sqlDateAndTimeTimeZone; + private boolean sqlDateAndTimeTimeZoneSet; private String booleanFormat; - private String trueStringValue; // deduced from booleanFormat - private String falseStringValue; // deduced from booleanFormat private TemplateExceptionHandler templateExceptionHandler; private ArithmeticEngine arithmeticEngine; private ObjectWrapper objectWrapper; @@ -347,24 +340,27 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces private Boolean showErrorTips; private Boolean apiBuiltinEnabled; private Boolean logTemplateExceptions; - private Map<String, ? extends TemplateDateFormatFactory> customDateFormats; - private Map<String, ? extends TemplateNumberFormatFactory> customNumberFormats; + private Map<String, TemplateDateFormatFactory> customDateFormats; + private Map<String, TemplateNumberFormatFactory> customNumberFormats; private LinkedHashMap<String, String> autoImports; private ArrayList<String> autoIncludes; private Boolean lazyImports; private Boolean lazyAutoImports; private boolean lazyAutoImportsSet; - + private Map<Object, Object> customAttributes; + /** * Called by the {@link Configuration} constructor, initializes the fields to their {@link Configuration}-level * default without marking them as set. */ + // TODO Move to Configuration(Builder) constructor MutableProcessingConfiguration(Version incompatibleImprovements) { _CoreAPI.checkVersionNotNullAndSupported(incompatibleImprovements); parent = null; locale = Configuration.getDefaultLocale(); timeZone = Configuration.getDefaultTimeZone(); - sqlDataAndTimeTimeZone = null; + sqlDateAndTimeTimeZone = null; + sqlDateAndTimeTimeZoneSet = true; numberFormat = "number"; timeFormat = ""; dateFormat = ""; @@ -379,14 +375,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces logTemplateExceptions = Boolean.FALSE; // outputEncoding and urlEscapingCharset defaults to null, // which means "not specified" - setBooleanFormat(C_TRUE_FALSE); - + setBooleanFormat(TemplateBooleanFormat.C_TRUE_FALSE); customDateFormats = Collections.emptyMap(); customNumberFormats = Collections.emptyMap(); - + outputEncodingSet = true; + urlEscapingCharsetSet = true; + lazyImports = false; lazyAutoImportsSet = true; - initAutoImportsMap(); initAutoIncludesList(); } @@ -420,7 +416,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * @return The parent {@link MutableProcessingConfiguration} object, or {@code null} if this is the root {@link MutableProcessingConfiguration} object * (i.e, if it's the {@link Configuration} object). */ - public final MutableProcessingConfiguration getParent() { + public final ProcessingConfiguration getParent() { return parent; } @@ -429,7 +425,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * template - the included template becomes the parent configurable during * its evaluation. */ - void setParent(MutableProcessingConfiguration parent) { + void setParent(ProcessingConfiguration parent) { this.parent = parent; } @@ -454,9 +450,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces @Override public Locale getLocale() { - return locale != null ? locale : parent.getLocale(); + return isLocaleSet() ? locale : getInheritedLocale(); } + protected abstract Locale getInheritedLocale(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -496,9 +494,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public TimeZone getTimeZone() { - return timeZone != null ? timeZone : parent.getTimeZone(); + return isTimeZoneSet() ? timeZone : getInheritedTimeZone(); } - + + protected abstract TimeZone getInheritedTimeZone(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -571,8 +571,8 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * @since 2.3.21 */ public void setSQLDateAndTimeTimeZone(TimeZone tz) { - sqlDataAndTimeTimeZone = tz; - sqlDataAndTimeTimeZoneSet = true; + sqlDateAndTimeTimeZone = tz; + sqlDateAndTimeTimeZoneSet = true; } /** @@ -595,11 +595,13 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public TimeZone getSQLDateAndTimeTimeZone() { - return sqlDataAndTimeTimeZoneSet - ? sqlDataAndTimeTimeZone - : (parent != null ? parent.getSQLDateAndTimeTimeZone() : null); + return sqlDateAndTimeTimeZoneSet + ? sqlDateAndTimeTimeZone + : getInheritedSQLDateAndTimeTimeZone(); } - + + protected abstract TimeZone getInheritedSQLDateAndTimeTimeZone(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -607,7 +609,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public boolean isSQLDateAndTimeTimeZoneSet() { - return sqlDataAndTimeTimeZoneSet; + return sqlDateAndTimeTimeZoneSet; } /** @@ -653,9 +655,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public String getNumberFormat() { - return numberFormat != null ? numberFormat : parent.getNumberFormat(); + return isNumberFormatSet() ? numberFormat : getInheritedNumberFormat(); } + protected abstract String getInheritedNumberFormat(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -682,10 +686,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * @since 2.3.24 */ @Override - public Map<String, ? extends TemplateNumberFormatFactory> getCustomNumberFormats() { - return customNumberFormats == null ? parent.getCustomNumberFormats() : customNumberFormats; + public Map<String, TemplateNumberFormatFactory> getCustomNumberFormats() { + return isCustomNumberFormatsSet() ? customNumberFormats : getInheritedCustomNumberFormats(); } + protected abstract Map<String, TemplateNumberFormatFactory> getInheritedCustomNumberFormats(); + /** * Associates names with formatter factories, which then can be referred by the {@link #setNumberFormat(String) * number_format} setting with values starting with <code>@<i>name</i></code>. Beware, if you specify any custom @@ -700,7 +706,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * * @since 2.3.24 */ - public void setCustomNumberFormats(Map<String, ? extends TemplateNumberFormatFactory> customNumberFormats) { + public void setCustomNumberFormats(Map<String, TemplateNumberFormatFactory> customNumberFormats) { _NullArgumentException.check("customNumberFormats", customNumberFormats); validateFormatNames(customNumberFormats.keySet()); this.customNumberFormats = customNumberFormats; @@ -709,7 +715,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces /** * Fluent API equivalent of {@link #setCustomNumberFormats(Map)} */ - public SelfT customNumberFormats(Map<String, ? extends TemplateNumberFormatFactory> value) { + public SelfT customNumberFormats(Map<String, TemplateNumberFormatFactory> value) { setCustomNumberFormats(value); return self(); } @@ -752,6 +758,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * * @since 2.3.24 */ + @Override public TemplateNumberFormatFactory getCustomNumberFormat(String name) { TemplateNumberFormatFactory r; if (customNumberFormats != null) { @@ -760,20 +767,24 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return r; } } - return parent != null ? parent.getCustomNumberFormat(name) : null; + return getInheritedCustomNumberFormat(name); } - + + protected abstract TemplateNumberFormatFactory getInheritedCustomNumberFormat(String name); + /** * Tells if this configurable object or its parent defines any custom formats. * * @since 2.3.24 */ public boolean hasCustomFormats() { - return customNumberFormats != null && !customNumberFormats.isEmpty() - || customDateFormats != null && !customDateFormats.isEmpty() - || getParent() != null && getParent().hasCustomFormats(); + return isCustomNumberFormatsSet() && !customNumberFormats.isEmpty() + || isCustomDateFormatsSet() && !customDateFormats.isEmpty() + || getInheritedHasCustomFormats(); } - + + protected abstract boolean getInheritedHasCustomFormats(); + /** * The string value for the boolean {@code true} and {@code false} values, intended for human audience (not for a * computer language), separated with comma. For example, {@code "yes,no"}. Note that white-space is significant, @@ -797,16 +808,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } this.booleanFormat = booleanFormat; - - if (booleanFormat.equals(C_TRUE_FALSE)) { - // C_TRUE_FALSE is the default for BC, but it's not a good default for human audience formatting, so we - // pretend that it wasn't set. - trueStringValue = null; - falseStringValue = null; - } else { - trueStringValue = booleanFormat.substring(0, commaIdx); - falseStringValue = booleanFormat.substring(commaIdx + 1); - } } /** @@ -822,9 +823,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public String getBooleanFormat() { - return booleanFormat != null ? booleanFormat : parent.getBooleanFormat(); + return isBooleanFormatSet() ? booleanFormat : getInheritedBooleanFormat(); } - + + protected abstract String getInheritedBooleanFormat(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -834,75 +837,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces public boolean isBooleanFormatSet() { return booleanFormat != null; } - - String formatBoolean(boolean value, boolean fallbackToTrueFalse) throws TemplateException { - if (value) { - String s = getTrueStringValue(); - if (s == null) { - if (fallbackToTrueFalse) { - return MiscUtil.C_TRUE; - } else { - throw new _MiscTemplateException(getNullBooleanFormatErrorDescription()); - } - } else { - return s; - } - } else { - String s = getFalseStringValue(); - if (s == null) { - if (fallbackToTrueFalse) { - return MiscUtil.C_FALSE; - } else { - throw new _MiscTemplateException(getNullBooleanFormatErrorDescription()); - } - } else { - return s; - } - } - } - - private _ErrorDescriptionBuilder getNullBooleanFormatErrorDescription() { - return new _ErrorDescriptionBuilder( - "Can't convert boolean to string automatically, because the \"", BOOLEAN_FORMAT_KEY ,"\" setting was ", - new _DelayedJQuote(getBooleanFormat()), - (getBooleanFormat().equals(C_TRUE_FALSE) - ? ", which is the legacy default computer-language format, and hence isn't accepted." - : ".") - ).tips( - "If you just want \"true\"/\"false\" result as you are generting computer-language output, " - + "use \"?c\", like ${myBool?c}.", - "You can write myBool?string('yes', 'no') and like to specify boolean formatting in place.", - new Object[] { - "If you need the same two values on most places, the programmers should set the \"", - BOOLEAN_FORMAT_KEY ,"\" setting to something like \"yes,no\"." } - ); - } - - /** - * Returns the string to which {@code true} is converted to for human audience, or {@code null} if automatic - * coercion to string is not allowed. The default value is {@code null}. - * - * <p>This value is deduced from the {@code "boolean_format"} setting. - * Confusingly, for backward compatibility (at least until 2.4) that defaults to {@code "true,false"}, yet this - * defaults to {@code null}. That's so because {@code "true,false"} is treated exceptionally, as that default is a - * historical mistake in FreeMarker, since it targets computer language output, not human writing. Thus it's - * ignored. - * - * @since 2.3.20 - */ - String getTrueStringValue() { - // The first step deliberately tests booleanFormat instead of trueStringValue! - return booleanFormat != null ? trueStringValue : (parent != null ? parent.getTrueStringValue() : null); - } - - /** - * Same as {@link #getTrueStringValue()} but with {@code false}. - * @since 2.3.20 - */ - String getFalseStringValue() { - // The first step deliberately tests booleanFormat instead of falseStringValue! - return booleanFormat != null ? falseStringValue : (parent != null ? parent.getFalseStringValue() : null); - } /** * Sets the format used to convert {@link java.util.Date}-s to string-s that are time (no date part) values, @@ -930,9 +864,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public String getTimeFormat() { - return timeFormat != null ? timeFormat : parent.getTimeFormat(); + return isTimeFormatSet() ? timeFormat : getInheritedTimeFormat(); } + protected abstract String getInheritedTimeFormat(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -969,9 +905,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public String getDateFormat() { - return dateFormat != null ? dateFormat : parent.getDateFormat(); + return isDateFormatSet() ? dateFormat : getInheritedDateFormat(); } + protected abstract String getInheritedDateFormat(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1086,9 +1024,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public String getDateTimeFormat() { - return dateTimeFormat != null ? dateTimeFormat : parent.getDateTimeFormat(); + return isDateTimeFormatSet() ? dateTimeFormat : getInheritedDateTimeFormat(); } - + + protected abstract String getInheritedDateTimeFormat(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1115,10 +1055,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * @since 2.3.24 */ @Override - public Map<String, ? extends TemplateDateFormatFactory> getCustomDateFormats() { - return customDateFormats == null ? parent.getCustomDateFormats() : customDateFormats; + public Map<String, TemplateDateFormatFactory> getCustomDateFormats() { + return isCustomDateFormatsSet() ? customDateFormats : getInheritedCustomDateFormats(); } + protected abstract Map<String, TemplateDateFormatFactory> getInheritedCustomDateFormats(); + /** * Associates names with formatter factories, which then can be referred by the {@link #setDateTimeFormat(String) * date_format}, {@link #setDateTimeFormat(String) time_format}, and {@link #setDateTimeFormat(String) @@ -1134,7 +1076,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * * @since 2.3.24 */ - public void setCustomDateFormats(Map<String, ? extends TemplateDateFormatFactory> customDateFormats) { + public void setCustomDateFormats(Map<String, TemplateDateFormatFactory> customDateFormats) { _NullArgumentException.check("customDateFormats", customDateFormats); validateFormatNames(customDateFormats.keySet()); this.customDateFormats = customDateFormats; @@ -1143,7 +1085,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces /** * Fluent API equivalent of {@link #setCustomDateFormats(Map)} */ - public SelfT customDateFormats(Map<String, ? extends TemplateDateFormatFactory> value) { + public SelfT customDateFormats(Map<String, TemplateDateFormatFactory> value) { setCustomDateFormats(value); return self(); } @@ -1163,6 +1105,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * * @since 2.3.24 */ + @Override public TemplateDateFormatFactory getCustomDateFormat(String name) { TemplateDateFormatFactory r; if (customDateFormats != null) { @@ -1171,9 +1114,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return r; } } - return parent != null ? parent.getCustomDateFormat(name) : null; + return getInheritedCustomDateFormat(name); } - + + protected abstract TemplateDateFormatFactory getInheritedCustomDateFormat(String name); + /** * Sets the exception handler used to handle exceptions occurring inside templates. * The default is {@link TemplateExceptionHandler#DEBUG_HANDLER}. The recommended values are: @@ -1212,10 +1157,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public TemplateExceptionHandler getTemplateExceptionHandler() { - return templateExceptionHandler != null - ? templateExceptionHandler : parent.getTemplateExceptionHandler(); + return isTemplateExceptionHandlerSet() + ? templateExceptionHandler : getInheritedTemplateExceptionHandler(); } + protected abstract TemplateExceptionHandler getInheritedTemplateExceptionHandler(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1248,10 +1195,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public ArithmeticEngine getArithmeticEngine() { - return arithmeticEngine != null - ? arithmeticEngine : parent.getArithmeticEngine(); + return isArithmeticEngineSet() + ? arithmeticEngine : getInheritedArithmeticEngine(); } + protected abstract ArithmeticEngine getInheritedArithmeticEngine(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1284,10 +1233,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public ObjectWrapper getObjectWrapper() { - return objectWrapper != null - ? objectWrapper : parent.getObjectWrapper(); + return isObjectWrapperSet() + ? objectWrapper : getInheritedObjectWrapper(); } + protected abstract ObjectWrapper getInheritedObjectWrapper(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1321,11 +1272,13 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces @Override public Charset getOutputEncoding() { - return outputEncodingSet + return isOutputEncodingSet() ? outputEncoding - : (parent != null ? parent.getOutputEncoding() : null); + : getInheritedOutputEncoding(); } + protected abstract Charset getInheritedOutputEncoding(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1357,11 +1310,13 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces @Override public Charset getURLEscapingCharset() { - return urlEscapingCharsetSet + return isURLEscapingCharsetSet() ? urlEscapingCharset - : (parent != null ? parent.getURLEscapingCharset() : null); + : getInheritedURLEscapingCharset(); } + protected abstract Charset getInheritedURLEscapingCharset(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1407,10 +1362,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public TemplateClassResolver getNewBuiltinClassResolver() { - return newBuiltinClassResolver != null - ? newBuiltinClassResolver : parent.getNewBuiltinClassResolver(); + return isNewBuiltinClassResolverSet() + ? newBuiltinClassResolver : getInheritedNewBuiltinClassResolver(); } + protected abstract TemplateClassResolver getInheritedNewBuiltinClassResolver(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1456,11 +1413,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public boolean getAutoFlush() { - return autoFlush != null - ? autoFlush.booleanValue() - : (parent != null ? parent.getAutoFlush() : true); + return isAutoFlushSet() ? autoFlush.booleanValue() : getInheritedAutoFlush(); } + protected abstract boolean getInheritedAutoFlush(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1496,11 +1453,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public boolean getShowErrorTips() { - return showErrorTips != null - ? showErrorTips.booleanValue() - : (parent != null ? parent.getShowErrorTips() : true); + return isShowErrorTipsSet() ? showErrorTips : getInheritedShowErrorTips(); } + protected abstract boolean getInheritedShowErrorTips(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1534,17 +1491,19 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * * @since 2.3.22 */ - public boolean isAPIBuiltinEnabled() { - return apiBuiltinEnabled != null - ? apiBuiltinEnabled.booleanValue() - : (parent != null ? parent.isAPIBuiltinEnabled() : false); + @Override + public boolean getAPIBuiltinEnabled() { + return isAPIBuiltinEnabledSet() ? apiBuiltinEnabled : getInheritedAPIBuiltinEnabled(); } + protected abstract boolean getInheritedAPIBuiltinEnabled(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * * @since 2.3.24 */ + @Override public boolean isAPIBuiltinEnabledSet() { return apiBuiltinEnabled != null; } @@ -1561,7 +1520,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * @since 2.3.22 */ public void setLogTemplateExceptions(boolean value) { - logTemplateExceptions = Boolean.valueOf(value); + logTemplateExceptions = value; } /** @@ -1571,11 +1530,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public boolean getLogTemplateExceptions() { - return logTemplateExceptions != null - ? logTemplateExceptions.booleanValue() - : (parent != null ? parent.getLogTemplateExceptions() : true); + return isLogTemplateExceptionsSet() ? logTemplateExceptions : getInheritedLogTemplateExceptions(); } + protected abstract boolean getInheritedLogTemplateExceptions(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1593,9 +1552,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public boolean getLazyImports() { - return lazyImports != null ? lazyImports.booleanValue() : parent.getLazyImports(); + return isLazyImportsSet() ? lazyImports : getInheritedLazyImports(); } - + + protected abstract boolean getInheritedLazyImports(); + /** * Specifies if {@code <#import ...>} (and {@link Environment#importLib(String, String)}) should delay the loading * and processing of the imported templates until the content of the imported namespace is actually accessed. This @@ -1619,7 +1580,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * @since 2.3.25 */ public void setLazyImports(boolean lazyImports) { - this.lazyImports = Boolean.valueOf(lazyImports); + this.lazyImports = lazyImports; } /** @@ -1639,9 +1600,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public Boolean getLazyAutoImports() { - return lazyAutoImportsSet ? lazyAutoImports : parent.getLazyAutoImports(); + return isLazyAutoImportsSet() ? lazyAutoImports : getInheritedLazyAutoImports(); } + protected abstract Boolean getInheritedLazyAutoImports(); + /** * Specifies if {@linkplain #setAutoImports(Map) auto-imports} will be * {@link #setLazyImports(boolean) lazy imports}. This is useful to make the overhead of <em>unused</em> @@ -1776,9 +1739,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public Map<String, String> getAutoImports() { - return autoImports != null ? autoImports : parent.getAutoImports(); + return isAutoImportsSet() ? autoImports : getInheritedAutoImports(); } - + + protected abstract Map<String,String> getInheritedAutoImports(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -1870,9 +1835,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ @Override public List<String> getAutoIncludes() { - return autoIncludes != null ? autoIncludes : parent.getAutoIncludes(); + return isAutoIncludesSet() ? autoIncludes : getInheritedAutoIncludes(); } - + + protected abstract List<String> getInheritedAutoIncludes(); + /** * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}. * @@ -2491,14 +2458,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces */ protected final UnknownConfigurationSettingException unknownSettingException(String name) { Version removalVersion = getRemovalVersionForUnknownSetting(name); - return removalVersion != null + return removalVersion != null ? new UnknownConfigurationSettingException(name, removalVersion) : new UnknownConfigurationSettingException(name, getCorrectedNameForUnknownSetting(name)); } /** - * If a setting name is unknown because it was removed over time, then returns the version where it was removed, - * otherwise returns {@code null}. + * If a setting name is unknown because it was removed over time (not just renamed), then returns the version where + * it was removed, otherwise returns {@code null}. */ protected Version getRemovalVersionForUnknownSetting(String name) { if (name.equals("classic_compatible") || name.equals("classicCompatible")) { @@ -2565,31 +2532,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } boolean isCustomAttributeSet(Object key) { - return customAttributes != null && customAttributes.containsKey(key); - } - - /** - * For internal usage only, copies the custom attributes set directly on this objects into another - * {@link MutableProcessingConfiguration}. The target {@link MutableProcessingConfiguration} is assumed to be not seen be other thread than the current - * one yet. (That is, the operation is not synchronized on the target {@link MutableProcessingConfiguration}, only on the source - * {@link MutableProcessingConfiguration}) - * - * @since 2.3.24 - */ - void copyDirectCustomAttributes(MutableProcessingConfiguration target, boolean overwriteExisting) { - if (customAttributes == null) { - return; - } - for (Entry<?, ?> custAttrEnt : customAttributes.entrySet()) { - Object custAttrKey = custAttrEnt.getKey(); - if (overwriteExisting || !target.isCustomAttributeSet(custAttrKey)) { - if (custAttrKey instanceof String) { - target.setCustomAttribute((String) custAttrKey, custAttrEnt.getValue()); - } else { - target.setCustomAttribute(custAttrKey, custAttrEnt.getValue()); - } - } - } + return isCustomAttributesSet() && customAttributes.containsKey(key); } /** @@ -2673,19 +2616,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces r = null; } if (r == null && parent != null) { - return parent.getCustomAttribute(name); + return getInheritedCustomAttribute(name); } return r; } - - /** - * Executes the auto-imports and auto-includes for the main template of this environment. - * This is not meant to be called or overridden by code outside of FreeMarker. - */ - protected void doAutoImportsAndIncludes(Environment env) - throws TemplateException, IOException { - if (parent != null) parent.doAutoImportsAndIncludes(env); - } + + protected abstract Object getInheritedCustomAttribute(Object name); protected final List<String> parseAsList(String text) throws GenericParseException { return new SettingStringParser(text).parseAsList(); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/ParserAndProcessingConfiguration.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ParserAndProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/ParserAndProcessingConfiguration.java new file mode 100644 index 0000000..9398242 --- /dev/null +++ b/src/main/java/org/apache/freemarker/core/ParserAndProcessingConfiguration.java @@ -0,0 +1,29 @@ +/* + * 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.freemarker.core; + +/** + * <b>Don't implement this interface yourself</b>; use the existing implementation(s). This interface is the union of + * {@link ProcessingConfiguration} and {@link ParserConfiguration}, which is useful for declaring types for values + * that must implement both interfaces. + */ +public interface ParserAndProcessingConfiguration extends ParserConfiguration, ProcessingConfiguration { + // No additional method +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/ParserConfiguration.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ParserConfiguration.java b/src/main/java/org/apache/freemarker/core/ParserConfiguration.java index e515826..599adbb 100644 --- a/src/main/java/org/apache/freemarker/core/ParserConfiguration.java +++ b/src/main/java/org/apache/freemarker/core/ParserConfiguration.java @@ -31,12 +31,13 @@ import org.apache.freemarker.core.outputformat.OutputFormat; * implementation. * * @see ProcessingConfiguration - * @since 2.3.24 */ public interface ParserConfiguration { TemplateLanguage getTemplateLanguage(); + boolean isTemplateLanguageSet(); + /** * See {@link Configuration#getTagSyntax()}. */ @@ -147,4 +148,6 @@ public interface ParserConfiguration { */ Charset getSourceEncoding(); + boolean isSourceEncodingSet(); + } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java index 33b028e..b224a01 100644 --- a/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java +++ b/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java @@ -97,7 +97,9 @@ public interface ProcessingConfiguration { /** * Getter pair of {@link MutableProcessingConfiguration#setCustomNumberFormats(Map)}. */ - Map<String, ? extends TemplateNumberFormatFactory> getCustomNumberFormats(); + Map<String, TemplateNumberFormatFactory> getCustomNumberFormats(); + + TemplateNumberFormatFactory getCustomNumberFormat(String name); /** * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading @@ -106,6 +108,8 @@ public interface ProcessingConfiguration { */ boolean isCustomNumberFormatsSet(); + boolean hasCustomFormats(); + /** * Getter pair of {@link MutableProcessingConfiguration#setBooleanFormat(String)}. */ @@ -157,7 +161,9 @@ public interface ProcessingConfiguration { /** * Getter pair of {@link MutableProcessingConfiguration#setCustomDateFormats(Map)}. */ - Map<String, ? extends TemplateDateFormatFactory> getCustomDateFormats(); + Map<String, TemplateDateFormatFactory> getCustomDateFormats(); + + TemplateDateFormatFactory getCustomDateFormat(String name); /** * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading @@ -238,6 +244,10 @@ public interface ProcessingConfiguration { */ boolean isNewBuiltinClassResolverSet(); + boolean getAPIBuiltinEnabled(); + + boolean isAPIBuiltinEnabledSet(); + /** * Getter pair of {@link MutableProcessingConfiguration#setAutoFlush(boolean)}. */ http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/Template.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/Template.java b/src/main/java/org/apache/freemarker/core/Template.java index a82c131..dcde5d9 100644 --- a/src/main/java/org/apache/freemarker/core/Template.java +++ b/src/main/java/org/apache/freemarker/core/Template.java @@ -38,9 +38,11 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.TimeZone; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; +import org.apache.freemarker.core.arithmetic.ArithmeticEngine; import org.apache.freemarker.core.debug._DebuggerService; import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateHashModel; @@ -53,6 +55,8 @@ import org.apache.freemarker.core.templateresolver.TemplateLookupStrategy; import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateResolver; import org.apache.freemarker.core.util.BugException; import org.apache.freemarker.core.util._NullArgumentException; +import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory; +import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; /** * <p> @@ -111,6 +115,10 @@ public class Template extends MutableProcessingConfiguration<Template> implement this.name = name; this.sourceName = sourceName; templateLanguageVersion = normalizeTemplateLanguageVersion(cfg.getIncompatibleImprovements()); + if (customParserConfiguration instanceof TemplateConfiguration.Builder) { + throw new IllegalArgumentException("Using TemplateConfiguration.Builder as Template constructor " + + "argument is not allowed; the TemplateConfiguration that it has built is needed instead."); + } parserConfiguration = customParserConfiguration != null ? customParserConfiguration : getConfiguration(); } @@ -732,6 +740,146 @@ public class Template extends MutableProcessingConfiguration<Template> implement return buf.toString(); } + @Override + protected Locale getInheritedLocale() { + return getParent().getLocale(); + } + + @Override + protected TimeZone getInheritedTimeZone() { + return getParent().getTimeZone(); + } + + @Override + protected TimeZone getInheritedSQLDateAndTimeTimeZone() { + return getParent().getSQLDateAndTimeTimeZone(); + } + + @Override + protected String getInheritedNumberFormat() { + return getParent().getNumberFormat(); + } + + @Override + protected Map<String, TemplateNumberFormatFactory> getInheritedCustomNumberFormats() { + return getParent().getCustomNumberFormats(); + } + + @Override + protected TemplateNumberFormatFactory getInheritedCustomNumberFormat(String name) { + return getParent().getCustomNumberFormat(name); + } + + @Override + protected boolean getInheritedHasCustomFormats() { + return getParent().hasCustomFormats(); + } + + @Override + protected String getInheritedBooleanFormat() { + return getParent().getBooleanFormat(); + } + + @Override + protected String getInheritedTimeFormat() { + return getParent().getTimeFormat(); + } + + @Override + protected String getInheritedDateFormat() { + return getParent().getDateFormat(); + } + + @Override + protected String getInheritedDateTimeFormat() { + return getParent().getDateTimeFormat(); + } + + @Override + protected Map<String, TemplateDateFormatFactory> getInheritedCustomDateFormats() { + return getParent().getCustomDateFormats(); + } + + @Override + protected TemplateDateFormatFactory getInheritedCustomDateFormat(String name) { + return getParent().getCustomDateFormat(name); + } + + @Override + protected TemplateExceptionHandler getInheritedTemplateExceptionHandler() { + return getParent().getTemplateExceptionHandler(); + } + + @Override + protected ArithmeticEngine getInheritedArithmeticEngine() { + return getParent().getArithmeticEngine(); + } + + @Override + protected ObjectWrapper getInheritedObjectWrapper() { + return getParent().getObjectWrapper(); + } + + @Override + protected Charset getInheritedOutputEncoding() { + return getParent().getOutputEncoding(); + } + + @Override + protected Charset getInheritedURLEscapingCharset() { + return getParent().getURLEscapingCharset(); + } + + @Override + protected TemplateClassResolver getInheritedNewBuiltinClassResolver() { + return getParent().getNewBuiltinClassResolver(); + } + + @Override + protected boolean getInheritedAutoFlush() { + return getParent().getAutoFlush(); + } + + @Override + protected boolean getInheritedShowErrorTips() { + return getParent().getShowErrorTips(); + } + + @Override + protected boolean getInheritedAPIBuiltinEnabled() { + return getParent().getAPIBuiltinEnabled(); + } + + @Override + protected boolean getInheritedLogTemplateExceptions() { + return getParent().getLogTemplateExceptions(); + } + + @Override + protected boolean getInheritedLazyImports() { + return getParent().getLazyImports(); + } + + @Override + protected Boolean getInheritedLazyAutoImports() { + return getParent().getLazyAutoImports(); + } + + @Override + protected Map<String, String> getInheritedAutoImports() { + return getParent().getAutoImports(); + } + + @Override + protected List<String> getInheritedAutoIncludes() { + return getParent().getAutoIncludes(); + } + + @Override + protected Object getInheritedCustomAttribute(Object name) { + return getParent().getCustomAttribute(name); + } + /** * Reader that builds up the line table info for us, and also helps in working around JavaCC's exception * suppression.
