http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d61a45d/src/main/java/org/apache/freemarker/core/ConfigurationException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ConfigurationException.java b/src/main/java/org/apache/freemarker/core/ConfigurationException.java index 42ab6e1..5b61cca 100644 --- a/src/main/java/org/apache/freemarker/core/ConfigurationException.java +++ b/src/main/java/org/apache/freemarker/core/ConfigurationException.java @@ -23,7 +23,7 @@ package org.apache.freemarker.core; * Error while configuring FreeMarker. */ @SuppressWarnings("serial") -public class ConfigurationException extends Exception { +public class ConfigurationException extends RuntimeException { public ConfigurationException(String message, Throwable cause) { super(message, cause);
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d61a45d/src/main/java/org/apache/freemarker/core/ConfigurationSettingValueException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ConfigurationSettingValueException.java b/src/main/java/org/apache/freemarker/core/ConfigurationSettingValueException.java index c480418..3ed6512 100644 --- a/src/main/java/org/apache/freemarker/core/ConfigurationSettingValueException.java +++ b/src/main/java/org/apache/freemarker/core/ConfigurationSettingValueException.java @@ -18,30 +18,69 @@ */ package org.apache.freemarker.core; -import org.apache.freemarker.core.util._NullArgumentException; +import java.util.Date; + +import org.apache.freemarker.core.Configuration.ExtendableBuilder; import org.apache.freemarker.core.util._StringUtil; /** - * Thrown by {@link Configuration#setSetting(String, String)}; The setting name was recognized, but its value + * Thrown by {@link ExtendableBuilder#setSetting(String, String)}; The setting name was recognized, but its value * couldn't be parsed or the setting couldn't be set for some other reason. This exception should always have a * cause exception. */ @SuppressWarnings("serial") public class ConfigurationSettingValueException extends ConfigurationException { - ConfigurationSettingValueException(String name, String value, Throwable cause) { - super(createMessage(name, value, "; see cause exception.", ""), cause); - _NullArgumentException.check("cause", cause); + public ConfigurationSettingValueException(String name, String value, Throwable cause) { + this(name, value, true, null, cause); + } + + public ConfigurationSettingValueException(String name, String value, String reason) { + this(name, value, true, reason, null); } - ConfigurationSettingValueException(String name, String value, String reason) { - super(createMessage(name, value, ", because: ", reason)); - _NullArgumentException.check("reason", reason); + /** + * @param name + * The name of the setting + * @param value + * The value of the setting + * @param showValue + * Whether the value of the setting should be shown in the error message. Set to {@code false} if you want + * to avoid {@link #toString()}-ing the {@code value}. + * @param reason + * The explanation of why setting the setting has failed; maybe {@code null}, especially if you have a cause + * exception anyway. + * @param cause + * The cause exception of this exception (why setting the setting was failed) + */ + public ConfigurationSettingValueException(String name, Object value, boolean showValue, String reason, + Throwable cause) { + super( + createMessage( + name, value, true, + reason != null ? ", because: " : (cause != null ? "; see cause exception." : null), + reason), + cause); } - private static String createMessage(String name, String value, String detail1, String detail2) { - return "Failed to set FreeMarker configuration setting " + _StringUtil.jQuote(name) - + " to value " + _StringUtil.jQuote(value) + detail1 + detail2; + private static String createMessage(String name, Object value, boolean showValue, String detail1, String detail2) { + StringBuilder sb = new StringBuilder(64); + sb.append("Failed to set FreeMarker configuration setting ").append(_StringUtil.jQuote(name)); + if (showValue) { + sb.append(" to value ") + .append( + value instanceof Number || value instanceof Boolean || value instanceof Date ? value + : _StringUtil.jQuote(value)); + } else { + sb.append(" to the specified value"); + } + if (detail1 != null) { + sb.append(detail1); + } + if (detail2 != null) { + sb.append(detail2); + } + return sb.toString(); } } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d61a45d/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 220f305..6713200 100644 --- a/src/main/java/org/apache/freemarker/core/Environment.java +++ b/src/main/java/org/apache/freemarker/core/Environment.java @@ -922,17 +922,17 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override - protected TemplateExceptionHandler getInheritedTemplateExceptionHandler() { + protected TemplateExceptionHandler getDefaultTemplateExceptionHandler() { return getMainTemplate().getTemplateExceptionHandler(); } @Override - protected ArithmeticEngine getInheritedArithmeticEngine() { + protected ArithmeticEngine getDefaultArithmeticEngine() { return getMainTemplate().getArithmeticEngine(); } @Override - protected ObjectWrapper getInheritedObjectWrapper() { + protected ObjectWrapper getDefaultObjectWrapper() { return getMainTemplate().getObjectWrapper(); } @@ -962,7 +962,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override - protected Locale getInheritedLocale() { + protected Locale getDefaultLocale() { return getMainTemplate().getLocale(); } @@ -991,7 +991,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override - protected TimeZone getInheritedTimeZone() { + protected TimeZone getDefaultTimeZone() { return getMainTemplate().getTimeZone(); } @@ -1020,7 +1020,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override - protected TimeZone getInheritedSQLDateAndTimeTimeZone() { + protected TimeZone getDefaultSQLDateAndTimeTimeZone() { return getMainTemplate().getSQLDateAndTimeTimeZone(); } @@ -1051,60 +1051,65 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override - protected Charset getInheritedURLEscapingCharset() { + protected Charset getDefaultURLEscapingCharset() { return getMainTemplate().getURLEscapingCharset(); } @Override - protected TemplateClassResolver getInheritedNewBuiltinClassResolver() { + protected TemplateClassResolver getDefaultNewBuiltinClassResolver() { return getMainTemplate().getNewBuiltinClassResolver(); } @Override - protected boolean getInheritedAutoFlush() { + protected boolean getDefaultAutoFlush() { return getMainTemplate().getAutoFlush(); } @Override - protected boolean getInheritedShowErrorTips() { + protected boolean getDefaultShowErrorTips() { return getMainTemplate().getShowErrorTips(); } @Override - protected boolean getInheritedAPIBuiltinEnabled() { + protected boolean getDefaultAPIBuiltinEnabled() { return getMainTemplate().getAPIBuiltinEnabled(); } @Override - protected boolean getInheritedLogTemplateExceptions() { + protected boolean getDefaultLogTemplateExceptions() { return getMainTemplate().getLogTemplateExceptions(); } @Override - protected boolean getInheritedLazyImports() { + protected boolean getDefaultLazyImports() { return getMainTemplate().getLazyImports(); } @Override - protected Boolean getInheritedLazyAutoImports() { + protected Boolean getDefaultLazyAutoImports() { return getMainTemplate().getLazyAutoImports(); } @Override - protected Map<String, String> getInheritedAutoImports() { + protected Map<String, String> getDefaultAutoImports() { return getMainTemplate().getAutoImports(); } @Override - protected List<String> getInheritedAutoIncludes() { + protected List<String> getDefaultAutoIncludes() { return getMainTemplate().getAutoIncludes(); } @Override - protected Object getInheritedCustomAttribute(Object name) { + protected Object getDefaultCustomAttribute(Object name) { return getMainTemplate().getCustomAttribute(name); } + @Override + protected Map<Object, Object> getDefaultCustomAttributes() { + return getMainTemplate().getCustomAttributes(); + } + /* * 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 @@ -1117,7 +1122,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override - protected Charset getInheritedOutputEncoding() { + protected Charset getDefaultOutputEncoding() { return getMainTemplate().getOutputEncoding(); } @@ -1220,22 +1225,22 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override - protected String getInheritedNumberFormat() { + protected String getDefaultNumberFormat() { return getMainTemplate().getNumberFormat(); } @Override - protected Map<String, TemplateNumberFormatFactory> getInheritedCustomNumberFormats() { + protected Map<String, TemplateNumberFormatFactory> getDefaultCustomNumberFormats() { return getMainTemplate().getCustomNumberFormats(); } @Override - protected TemplateNumberFormatFactory getInheritedCustomNumberFormat(String name) { + protected TemplateNumberFormatFactory getDefaultCustomNumberFormat(String name) { return getMainTemplate().getCustomNumberFormat(name); } @Override - protected String getInheritedBooleanFormat() { + protected String getDefaultBooleanFormat() { return getMainTemplate().getBooleanFormat(); } @@ -1530,7 +1535,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override - protected String getInheritedTimeFormat() { + protected String getDefaultTimeFormat() { return getMainTemplate().getTimeFormat(); } @@ -1548,7 +1553,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override - protected String getInheritedDateFormat() { + protected String getDefaultDateFormat() { return getMainTemplate().getDateFormat(); } @@ -1566,17 +1571,17 @@ public final class Environment extends MutableProcessingConfiguration<Environmen } @Override - protected String getInheritedDateTimeFormat() { + protected String getDefaultDateTimeFormat() { return getMainTemplate().getDateTimeFormat(); } @Override - protected Map<String, TemplateDateFormatFactory> getInheritedCustomDateFormats() { + protected Map<String, TemplateDateFormatFactory> getDefaultCustomDateFormats() { return getMainTemplate().getCustomDateFormats(); } @Override - protected TemplateDateFormatFactory getInheritedCustomDateFormat(String name) { + protected TemplateDateFormatFactory getDefaultCustomDateFormat(String name) { return getMainTemplate().getCustomDateFormat(name); } @@ -2083,7 +2088,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen if (tm instanceof TemplateTransformModel) { ttm = (TemplateTransformModel) tm; } else if (exp instanceof ASTExpVariable) { - tm = configuration.getSharedVariable(exp.toString()); + tm = configuration.getWrappedSharedVariable(exp.toString()); if (tm instanceof TemplateTransformModel) { ttm = (TemplateTransformModel) tm; } @@ -2148,7 +2153,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen result = rootDataModel.get(name); } if (result == null) { - result = configuration.getSharedVariable(name); + result = configuration.getWrappedSharedVariable(name); } return result; } @@ -2200,7 +2205,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen */ public Set getKnownVariableNames() throws TemplateModelException { // shared vars. - Set set = configuration.getSharedVariableNames(); + Set set = configuration.getSharedVariables().keySet(); // root hash if (rootDataModel instanceof TemplateHashModelEx) { @@ -2454,7 +2459,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen public TemplateModel get(String key) throws TemplateModelException { TemplateModel value = rootDataModel.get(key); if (value == null) { - value = configuration.getSharedVariable(key); + value = configuration.getWrappedSharedVariable(key); } return value; } @@ -2515,7 +2520,7 @@ public final class Environment extends MutableProcessingConfiguration<Environmen result = rootDataModel.get(key); } if (result == null) { - result = configuration.getSharedVariable(key); + result = configuration.getWrappedSharedVariable(key); } return result; } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d61a45d/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java index 2df4796..00a387d 100644 --- a/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java +++ b/src/main/java/org/apache/freemarker/core/MutableParsingAndProcessingConfiguration.java @@ -23,10 +23,10 @@ import java.io.InputStream; import java.nio.charset.Charset; import org.apache.freemarker.core.outputformat.OutputFormat; +import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat; import org.apache.freemarker.core.templateresolver.TemplateLoader; import org.apache.freemarker.core.util._NullArgumentException; -// TODO This will be the superclass of TemplateConfiguration.Builder and Configuration.Builder public abstract class MutableParsingAndProcessingConfiguration< SelfT extends MutableParsingAndProcessingConfiguration<SelfT>> extends MutableProcessingConfiguration<SelfT> @@ -42,22 +42,30 @@ public abstract class MutableParsingAndProcessingConfiguration< private Charset sourceEncoding; private Integer tabSize; - protected MutableParsingAndProcessingConfiguration(Version incompatibleImprovements) { - super(incompatibleImprovements); - } - protected MutableParsingAndProcessingConfiguration() { super(); } /** - * See {@link Configuration#setTagSyntax(int)}. + * Setter pair of {@link #getTagSyntax()}. */ public void setTagSyntax(int tagSyntax) { - Configuration.valideTagSyntaxValue(tagSyntax); + valideTagSyntaxValue(tagSyntax); this.tagSyntax = tagSyntax; } + // [FM3] Use enum; won't be needed + static void valideTagSyntaxValue(int tagSyntax) { + if (tagSyntax != ParsingConfiguration.AUTO_DETECT_TAG_SYNTAX + && tagSyntax != ParsingConfiguration.SQUARE_BRACKET_TAG_SYNTAX + && tagSyntax != ParsingConfiguration.ANGLE_BRACKET_TAG_SYNTAX) { + throw new IllegalArgumentException( + "\"tagSyntax\" can only be set to one of these: " + + "Configuration.AUTO_DETECT_TAG_SYNTAX, Configuration.ANGLE_BRACKET_SYNTAX, " + + "or Configuration.SQUARE_BRACKET_SYNTAX"); + } + } + /** * Fluent API equivalent of {@link #tagSyntax(int)} */ @@ -67,32 +75,42 @@ public abstract class MutableParsingAndProcessingConfiguration< } /** - * The getter pair of {@link #setTagSyntax(int)}. + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ParsingConfiguration}). */ + public void unsetTagSyntax() { + this.tagSyntax = null; + } + @Override public int getTagSyntax() { - return tagSyntax != null ? tagSyntax : getInheritedTagSyntax(); + return isTagSyntaxSet() ? tagSyntax : getDefaultTagSyntax(); } - protected abstract int getInheritedTagSyntax(); + /** + * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value + * from another {@link ParsingConfiguration}, or throws {@link SettingValueNotSetException}. + */ + protected abstract int getDefaultTagSyntax(); @Override public boolean isTagSyntaxSet() { return tagSyntax != null; } - /** - * See {@link Configuration#getTemplateLanguage()} - */ @Override public TemplateLanguage getTemplateLanguage() { - return isTemplateLanguageSet() ? templateLanguage : getInheritedTemplateLanguage(); + return isTemplateLanguageSet() ? templateLanguage : getDefaultTemplateLanguage(); } - protected abstract TemplateLanguage getInheritedTemplateLanguage(); + /** + * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value + * from another {@link ParsingConfiguration}, or throws {@link SettingValueNotSetException}. + */ + protected abstract TemplateLanguage getDefaultTemplateLanguage(); /** - * See {@link Configuration#setTemplateLanguage(TemplateLanguage)} + * Setter pair of {@link #getTemplateLanguage()}. */ public void setTemplateLanguage(TemplateLanguage templateLanguage) { _NullArgumentException.check("templateLanguage", templateLanguage); @@ -107,12 +125,21 @@ public abstract class MutableParsingAndProcessingConfiguration< return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ParsingConfiguration}). + */ + public void unsetTemplateLanguage() { + this.templateLanguage = null; + } + + @Override public boolean isTemplateLanguageSet() { return templateLanguage != null; } /** - * See {@link Configuration#setNamingConvention(int)}. + * Setter pair of {@link #getNamingConvention()}. */ public void setNamingConvention(int namingConvention) { Configuration.validateNamingConventionValue(namingConvention); @@ -128,15 +155,27 @@ public abstract class MutableParsingAndProcessingConfiguration< } /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ParsingConfiguration}). + */ + public void unsetNamingConvention() { + this.namingConvention = null; + } + + /** * The getter pair of {@link #setNamingConvention(int)}. */ @Override public int getNamingConvention() { return isNamingConventionSet() ? namingConvention - : getInheritedNamingConvention(); + : getDefaultNamingConvention(); } - protected abstract int getInheritedNamingConvention(); + /** + * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value + * from another {@link ParsingConfiguration}, or throws {@link SettingValueNotSetException}. + */ + protected abstract int getDefaultNamingConvention(); /** * Tells if this setting is set directly in this object or its value is inherited from the parent parsing configuration.. @@ -147,10 +186,10 @@ public abstract class MutableParsingAndProcessingConfiguration< } /** - * See {@link Configuration#setWhitespaceStripping(boolean)}. + * Setter pair of {@link ParsingConfiguration#getWhitespaceStripping()}. */ public void setWhitespaceStripping(boolean whitespaceStripping) { - this.whitespaceStripping = Boolean.valueOf(whitespaceStripping); + this.whitespaceStripping = whitespaceStripping; } /** @@ -162,15 +201,26 @@ public abstract class MutableParsingAndProcessingConfiguration< } /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ParsingConfiguration}). + */ + public void unsetWhitespaceStripping() { + this.whitespaceStripping = null; + } + + /** * The getter pair of {@link #getWhitespaceStripping()}. */ @Override public boolean getWhitespaceStripping() { - return isWhitespaceStrippingSet() ? whitespaceStripping.booleanValue() - : getInheritedWhitespaceStripping(); + return isWhitespaceStrippingSet() ? whitespaceStripping : getDefaultWhitespaceStripping(); } - protected abstract boolean getInheritedWhitespaceStripping(); + /** + * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value + * from another {@link ParsingConfiguration}, or throws {@link SettingValueNotSetException}. + */ + protected abstract boolean getDefaultWhitespaceStripping(); /** * Tells if this setting is set directly in this object or its value is inherited from the parent parsing configuration.. @@ -181,12 +231,24 @@ public abstract class MutableParsingAndProcessingConfiguration< } /** - * Sets the output format of the template; see {@link Configuration#setAutoEscapingPolicy(int)} for more. + * * Setter pair of {@link #getAutoEscapingPolicy()}. */ public void setAutoEscapingPolicy(int autoEscapingPolicy) { - Configuration.validateAutoEscapingPolicyValue(autoEscapingPolicy); + validateAutoEscapingPolicyValue(autoEscapingPolicy); + this.autoEscapingPolicy = autoEscapingPolicy; + } - this.autoEscapingPolicy = Integer.valueOf(autoEscapingPolicy); + // [FM3] Use enum; won't be needed + static void validateAutoEscapingPolicyValue(int autoEscapingPolicy) { + if (autoEscapingPolicy != ParsingConfiguration.ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY + && autoEscapingPolicy != ParsingConfiguration.ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY + && autoEscapingPolicy != ParsingConfiguration.DISABLE_AUTO_ESCAPING_POLICY) { + throw new IllegalArgumentException( + "\"tagSyntax\" can only be set to one of these: " + + "Configuration.ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY," + + "Configuration.ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY, " + + "or Configuration.DISABLE_AUTO_ESCAPING_POLICY"); + } } /** @@ -198,15 +260,26 @@ public abstract class MutableParsingAndProcessingConfiguration< } /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ParsingConfiguration}). + */ + public void unsetAutoEscapingPolicy() { + this.autoEscapingPolicy = null; + } + + /** * The getter pair of {@link #setAutoEscapingPolicy(int)}. */ @Override public int getAutoEscapingPolicy() { - return isAutoEscapingPolicySet() ? autoEscapingPolicy.intValue() - : getInheritedAutoEscapingPolicy(); + return isAutoEscapingPolicySet() ? autoEscapingPolicy : getDefaultAutoEscapingPolicy(); } - protected abstract int getInheritedAutoEscapingPolicy(); + /** + * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value + * from another {@link ParsingConfiguration}, or throws {@link SettingValueNotSetException}. + */ + protected abstract int getDefaultAutoEscapingPolicy(); /** * Tells if this setting is set directly in this object or its value is inherited from the parent parsing configuration.. @@ -217,14 +290,25 @@ public abstract class MutableParsingAndProcessingConfiguration< } /** - * Sets the output format of the template; see {@link Configuration#setOutputFormat(OutputFormat)} for more. + * Setter pair of {@link #getOutputFormat()}. */ public void setOutputFormat(OutputFormat outputFormat) { - _NullArgumentException.check("outputFormat", outputFormat); + if (outputFormat == null) { + throw new _NullArgumentException( + "outputFormat", + "You may meant: " + UndefinedOutputFormat.class.getSimpleName() + ".INSTANCE"); + } this.outputFormat = outputFormat; } /** + * Resets this setting to its initial state, as if it was never set. + */ + public void unsetOutputFormat() { + this.outputFormat = null; + } + + /** * Fluent API equivalent of {@link #setOutputFormat(OutputFormat)} */ public SelfT outputFormat(OutputFormat outputFormat) { @@ -232,15 +316,16 @@ public abstract class MutableParsingAndProcessingConfiguration< return self(); } - /** - * The getter pair of {@link #setOutputFormat(OutputFormat)}. - */ @Override public OutputFormat getOutputFormat() { - return isOutputFormatSet() ? outputFormat : getInheritedOutputFormat(); + return isOutputFormatSet() ? outputFormat : getDefaultOutputFormat(); } - protected abstract OutputFormat getInheritedOutputFormat(); + /** + * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value + * from another {@link ParsingConfiguration}, or throws {@link SettingValueNotSetException}. + */ + protected abstract OutputFormat getDefaultOutputFormat(); /** * Tells if this setting is set directly in this object or its value is inherited from the parent parsing configuration.. @@ -251,10 +336,10 @@ public abstract class MutableParsingAndProcessingConfiguration< } /** - * See {@link Configuration#setRecognizeStandardFileExtensions(boolean)}. + * Setter pair of {@link ParsingConfiguration#getRecognizeStandardFileExtensions()}. */ public void setRecognizeStandardFileExtensions(boolean recognizeStandardFileExtensions) { - this.recognizeStandardFileExtensions = Boolean.valueOf(recognizeStandardFileExtensions); + this.recognizeStandardFileExtensions = recognizeStandardFileExtensions; } /** @@ -266,15 +351,26 @@ public abstract class MutableParsingAndProcessingConfiguration< } /** + * Resets this setting to its initial state, as if it was never set. + */ + public void unsetRecognizeStandardFileExtensions() { + recognizeStandardFileExtensions = null; + } + + /** * Getter pair of {@link #setRecognizeStandardFileExtensions(boolean)}. */ @Override public boolean getRecognizeStandardFileExtensions() { - return isRecognizeStandardFileExtensionsSet() ? recognizeStandardFileExtensions.booleanValue() - : getInheritedRecognizeStandardFileExtensions(); + return isRecognizeStandardFileExtensionsSet() ? recognizeStandardFileExtensions + : getDefaultRecognizeStandardFileExtensions(); } - protected abstract boolean getInheritedRecognizeStandardFileExtensions(); + /** + * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value + * from another {@link ParsingConfiguration}, or throws {@link SettingValueNotSetException}. + */ + protected abstract boolean getDefaultRecognizeStandardFileExtensions(); /** * Tells if this setting is set directly in this object or its value is inherited from the parent parsing configuration.. @@ -286,10 +382,14 @@ public abstract class MutableParsingAndProcessingConfiguration< @Override public Charset getSourceEncoding() { - return isSourceEncodingSet() ? sourceEncoding : getInheritedSourceEncoding(); + return isSourceEncodingSet() ? sourceEncoding : getDefaultSourceEncoding(); } - protected abstract Charset getInheritedSourceEncoding(); + /** + * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value + * from another {@link ParsingConfiguration}, or throws {@link SettingValueNotSetException}. + */ + protected abstract Charset getDefaultSourceEncoding(); /** * The charset to be used when reading the template "file" that the {@link TemplateLoader} returns as binary @@ -308,16 +408,30 @@ public abstract class MutableParsingAndProcessingConfiguration< return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ParsingConfiguration}). + */ + public void unsetSourceEncoding() { + this.sourceEncoding = null; + } + + @Override public boolean isSourceEncodingSet() { return sourceEncoding != null; } /** - * See {@link Configuration#setTabSize(int)}. - * - * @since 2.3.25 + * Setter pair of {@link #getTabSize()}. */ public void setTabSize(int tabSize) { + if (tabSize < 1) { + throw new IllegalArgumentException("\"tabSize\" must be at least 1, but was " + tabSize); + } + // To avoid integer overflows: + if (tabSize > 256) { + throw new IllegalArgumentException("\"tabSize\" can't be more than 256, but was " + tabSize); + } this.tabSize = Integer.valueOf(tabSize); } @@ -330,16 +444,23 @@ public abstract class MutableParsingAndProcessingConfiguration< } /** - * Getter pair of {@link #setTabSize(int)}. - * - * @since 2.3.25 + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ParsingConfiguration}). */ + public void unsetTabSize() { + this.tabSize = null; + } + @Override public int getTabSize() { - return isTabSizeSet() ? tabSize.intValue() : getInheritedTabSize(); + return isTabSizeSet() ? tabSize.intValue() : getDefaultTabSize(); } - protected abstract int getInheritedTabSize(); + /** + * Returns the value the getter method returns when the setting is not set, possibly by inheriting the setting value + * from another {@link ParsingConfiguration}, or throws {@link SettingValueNotSetException}. + */ + protected abstract int getDefaultTabSize(); /** * Tells if this setting is set directly in this object or its value is inherited from the parent parsing configuration.. http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7d61a45d/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 a7daf31..c5c4c82 100644 --- a/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java +++ b/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java @@ -22,7 +22,6 @@ package org.apache.freemarker.core; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -56,7 +55,6 @@ import org.apache.freemarker.core.templateresolver.NotMatcher; import org.apache.freemarker.core.templateresolver.OrMatcher; import org.apache.freemarker.core.templateresolver.PathGlobMatcher; import org.apache.freemarker.core.templateresolver.PathRegexMatcher; -import org.apache.freemarker.core.templateresolver.TemplateLoader; import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateNameFormat; import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateNameFormatFM2; import org.apache.freemarker.core.util.FTLUtil; @@ -73,7 +71,7 @@ import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; /** * Extended by FreeMarker core classes (not by you) that support specifying {@link ProcessingConfiguration} setting - * values. <b>New abstract methods may be added anytime in future FreeMarker versions, so don't try to implement this + * values. <b>New abstract methods may be added any time in future FreeMarker versions, so don't try to implement this * interface yourself!</b> */ public abstract class MutableProcessingConfiguration<SelfT extends MutableProcessingConfiguration<SelfT>> @@ -337,48 +335,27 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces 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. + * Creates a new instance. Normally you do not need to use this constructor, + * as you don't use <code>MutableProcessingConfiguration</code> directly, but its subclasses. */ - // TODO Move to Configuration(Builder) constructor - MutableProcessingConfiguration(Version iciForDefaults) { - _CoreAPI.checkVersionNotNullAndSupported(iciForDefaults); - locale = Configuration.getDefaultLocale(); - timeZone = Configuration.getDefaultTimeZone(); - sqlDateAndTimeTimeZone = null; - sqlDateAndTimeTimeZoneSet = true; - numberFormat = "number"; - timeFormat = ""; - dateFormat = ""; - dateTimeFormat = ""; - templateExceptionHandler = Configuration.getDefaultTemplateExceptionHandler(); - arithmeticEngine = BigDecimalArithmeticEngine.INSTANCE; - objectWrapper = Configuration.getDefaultObjectWrapper(iciForDefaults); - autoFlush = Boolean.TRUE; - newBuiltinClassResolver = TemplateClassResolver.UNRESTRICTED_RESOLVER; - showErrorTips = Boolean.TRUE; - apiBuiltinEnabled = Boolean.FALSE; - logTemplateExceptions = Boolean.FALSE; - // outputEncoding and urlEscapingCharset defaults to null, - // which means "not specified" - setBooleanFormat(TemplateBooleanFormat.C_TRUE_FALSE); - customDateFormats = Collections.emptyMap(); - customNumberFormats = Collections.emptyMap(); - outputEncodingSet = true; - urlEscapingCharsetSet = true; + protected MutableProcessingConfiguration() { + // Empty + } - lazyImports = false; - lazyAutoImportsSet = true; - initAutoImportsMap(); - initAutoIncludesList(); + @Override + public Locale getLocale() { + return isLocaleSet() ? locale : getDefaultLocale(); } /** - * Creates a new instance. Normally you do not need to use this constructor, - * as you don't use <code>MutableProcessingConfiguration</code> directly, but its subclasses. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ - protected MutableProcessingConfiguration() { - // Empty + protected abstract Locale getDefaultLocale(); + + @Override + public boolean isLocaleSet() { + return locale != null; } /** @@ -397,21 +374,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } - @Override - public Locale getLocale() { - return isLocaleSet() ? locale : getInheritedLocale(); - } - - protected abstract Locale getInheritedLocale(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). */ - @Override - public boolean isLocaleSet() { - return locale != null; + public void unsetLocale() { + locale = null; } /** @@ -429,19 +397,25 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces setTimeZone(value); return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetTimeZone() { + this.timeZone = null; + } @Override public TimeZone getTimeZone() { - return isTimeZoneSet() ? timeZone : getInheritedTimeZone(); + return isTimeZoneSet() ? timeZone : getDefaultTimeZone(); } - protected abstract TimeZone getInheritedTimeZone(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract TimeZone getDefaultTimeZone(); + @Override public boolean isTimeZoneSet() { return timeZone != null; @@ -463,20 +437,28 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetSQLDateAndTimeTimeZone() { + sqlDateAndTimeTimeZone = null; + sqlDateAndTimeTimeZoneSet = false; + } + @Override public TimeZone getSQLDateAndTimeTimeZone() { return sqlDateAndTimeTimeZoneSet ? sqlDateAndTimeTimeZone - : getInheritedSQLDateAndTimeTimeZone(); + : getDefaultSQLDateAndTimeTimeZone(); } - protected abstract TimeZone getInheritedSQLDateAndTimeTimeZone(); - /** - * Tells if this setting is set directly in this object or its value is inherited from a parent processing configuration. - * - * @since 2.3.24 + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract TimeZone getDefaultSQLDateAndTimeTimeZone(); + @Override public boolean isSQLDateAndTimeTimeZoneSet() { return sqlDateAndTimeTimeZoneSet; @@ -498,18 +480,25 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetNumberFormat() { + numberFormat = null; + } + @Override public String getNumberFormat() { - return isNumberFormatSet() ? numberFormat : getInheritedNumberFormat(); + return isNumberFormatSet() ? numberFormat : getDefaultNumberFormat(); } - protected abstract String getInheritedNumberFormat(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract String getDefaultNumberFormat(); + @Override public boolean isNumberFormatSet() { return numberFormat != null; @@ -517,10 +506,10 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces @Override public Map<String, TemplateNumberFormatFactory> getCustomNumberFormats() { - return isCustomNumberFormatsSet() ? customNumberFormats : getInheritedCustomNumberFormats(); + return isCustomNumberFormatsSet() ? customNumberFormats : getDefaultCustomNumberFormats(); } - protected abstract Map<String, TemplateNumberFormatFactory> getInheritedCustomNumberFormats(); + protected abstract Map<String, TemplateNumberFormatFactory> getDefaultCustomNumberFormats(); /** * Setter pair of {@link #getCustomNumberFormats()}. Note that custom number formats are get through @@ -545,6 +534,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetCustomNumberFormats() { + customNumberFormats = null; + } + private void validateFormatNames(Set<String> keySet) { for (String name : keySet) { if (name.length() == 0) { @@ -568,13 +565,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } } - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. - * - * @since 2.3.24 - */ @Override public boolean isCustomNumberFormatsSet() { return customNumberFormats != null; @@ -589,10 +579,10 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return r; } } - return getInheritedCustomNumberFormat(name); + return getDefaultCustomNumberFormat(name); } - protected abstract TemplateNumberFormatFactory getInheritedCustomNumberFormat(String name); + protected abstract TemplateNumberFormatFactory getDefaultCustomNumberFormat(String name); /** * Setter pair of {@link #getBooleanFormat()}. @@ -617,21 +607,26 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces setBooleanFormat(value); return self(); } + + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetBooleanFormat() { + booleanFormat = null; + } @Override public String getBooleanFormat() { - return isBooleanFormatSet() ? booleanFormat : getInheritedBooleanFormat(); + return isBooleanFormatSet() ? booleanFormat : getDefaultBooleanFormat(); } - protected abstract String getInheritedBooleanFormat(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. - * - * @since 2.3.24 + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract String getDefaultBooleanFormat(); + @Override public boolean isBooleanFormatSet() { return booleanFormat != null; @@ -653,18 +648,25 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetTimeFormat() { + timeFormat = null; + } + @Override public String getTimeFormat() { - return isTimeFormatSet() ? timeFormat : getInheritedTimeFormat(); + return isTimeFormatSet() ? timeFormat : getDefaultTimeFormat(); } - protected abstract String getInheritedTimeFormat(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract String getDefaultTimeFormat(); + @Override public boolean isTimeFormatSet() { return timeFormat != null; @@ -686,18 +688,25 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetDateFormat() { + dateFormat = null; + } + @Override public String getDateFormat() { - return isDateFormatSet() ? dateFormat : getInheritedDateFormat(); + return isDateFormatSet() ? dateFormat : getDefaultDateFormat(); } - protected abstract String getInheritedDateFormat(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract String getDefaultDateFormat(); + @Override public boolean isDateFormatSet() { return dateFormat != null; @@ -719,18 +728,25 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetDateTimeFormat() { + this.dateTimeFormat = null; + } + @Override public String getDateTimeFormat() { - return isDateTimeFormatSet() ? dateTimeFormat : getInheritedDateTimeFormat(); + return isDateTimeFormatSet() ? dateTimeFormat : getDefaultDateTimeFormat(); } - protected abstract String getInheritedDateTimeFormat(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract String getDefaultDateTimeFormat(); + @Override public boolean isDateTimeFormatSet() { return dateTimeFormat != null; @@ -738,10 +754,10 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces @Override public Map<String, TemplateDateFormatFactory> getCustomDateFormats() { - return isCustomDateFormatsSet() ? customDateFormats : getInheritedCustomDateFormats(); + return isCustomDateFormatsSet() ? customDateFormats : getDefaultCustomDateFormats(); } - protected abstract Map<String, TemplateDateFormatFactory> getInheritedCustomDateFormats(); + protected abstract Map<String, TemplateDateFormatFactory> getDefaultCustomDateFormats(); /** * Setter pair of {@link #getCustomDateFormat(String)}. @@ -761,10 +777,13 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). */ + public void unsetCustomDateFormats() { + this.customDateFormats = null; + } + @Override public boolean isCustomDateFormatsSet() { return customDateFormats != null; @@ -779,10 +798,10 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return r; } } - return getInheritedCustomDateFormat(name); + return getDefaultCustomDateFormat(name); } - protected abstract TemplateDateFormatFactory getInheritedCustomDateFormat(String name); + protected abstract TemplateDateFormatFactory getDefaultCustomDateFormat(String name); /** * Setter pair of {@link #getTemplateExceptionHandler()} @@ -800,19 +819,26 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetTemplateExceptionHandler() { + templateExceptionHandler = null; + } + @Override public TemplateExceptionHandler getTemplateExceptionHandler() { return isTemplateExceptionHandlerSet() - ? templateExceptionHandler : getInheritedTemplateExceptionHandler(); + ? templateExceptionHandler : getDefaultTemplateExceptionHandler(); } - protected abstract TemplateExceptionHandler getInheritedTemplateExceptionHandler(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract TemplateExceptionHandler getDefaultTemplateExceptionHandler(); + @Override public boolean isTemplateExceptionHandlerSet() { return templateExceptionHandler != null; @@ -834,18 +860,25 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetArithmeticEngine() { + this.arithmeticEngine = null; + } + @Override public ArithmeticEngine getArithmeticEngine() { - return isArithmeticEngineSet() ? arithmeticEngine : getInheritedArithmeticEngine(); + return isArithmeticEngineSet() ? arithmeticEngine : getDefaultArithmeticEngine(); } - protected abstract ArithmeticEngine getInheritedArithmeticEngine(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract ArithmeticEngine getDefaultArithmeticEngine(); + @Override public boolean isArithmeticEngineSet() { return arithmeticEngine != null; @@ -860,6 +893,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetObjectWrapper() { + objectWrapper = null; + } + + /** * Fluent API equivalent of {@link #setObjectWrapper(ObjectWrapper)} */ public SelfT objectWrapper(ObjectWrapper value) { @@ -870,16 +911,15 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces @Override public ObjectWrapper getObjectWrapper() { return isObjectWrapperSet() - ? objectWrapper : getInheritedObjectWrapper(); + ? objectWrapper : getDefaultObjectWrapper(); } - protected abstract ObjectWrapper getInheritedObjectWrapper(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract ObjectWrapper getDefaultObjectWrapper(); + @Override public boolean isObjectWrapperSet() { return objectWrapper != null; @@ -901,20 +941,28 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetOutputEncoding() { + this.outputEncoding = null; + outputEncodingSet = false; + } + @Override public Charset getOutputEncoding() { return isOutputEncodingSet() ? outputEncoding - : getInheritedOutputEncoding(); + : getDefaultOutputEncoding(); } - protected abstract Charset getInheritedOutputEncoding(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract Charset getDefaultOutputEncoding(); + @Override public boolean isOutputEncodingSet() { return outputEncodingSet; @@ -936,18 +984,26 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetURLEscapingCharset() { + this.urlEscapingCharset = null; + urlEscapingCharsetSet = false; + } + @Override public Charset getURLEscapingCharset() { - return isURLEscapingCharsetSet() ? urlEscapingCharset : getInheritedURLEscapingCharset(); + return isURLEscapingCharsetSet() ? urlEscapingCharset : getDefaultURLEscapingCharset(); } - protected abstract Charset getInheritedURLEscapingCharset(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract Charset getDefaultURLEscapingCharset(); + @Override public boolean isURLEscapingCharsetSet() { return urlEscapingCharsetSet; @@ -969,21 +1025,26 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetNewBuiltinClassResolver() { + this.newBuiltinClassResolver = null; + } + @Override public TemplateClassResolver getNewBuiltinClassResolver() { return isNewBuiltinClassResolverSet() - ? newBuiltinClassResolver : getInheritedNewBuiltinClassResolver(); + ? newBuiltinClassResolver : getDefaultNewBuiltinClassResolver(); } - protected abstract TemplateClassResolver getInheritedNewBuiltinClassResolver(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. - * - * @since 2.3.24 + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract TemplateClassResolver getDefaultNewBuiltinClassResolver(); + @Override public boolean isNewBuiltinClassResolverSet() { return newBuiltinClassResolver != null; @@ -993,7 +1054,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * Setter pair of {@link #getAutoFlush()} */ public void setAutoFlush(boolean autoFlush) { - this.autoFlush = Boolean.valueOf(autoFlush); + this.autoFlush = autoFlush; } /** @@ -1004,20 +1065,25 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetAutoFlush() { + this.autoFlush = null; + } + @Override public boolean getAutoFlush() { - return isAutoFlushSet() ? autoFlush.booleanValue() : getInheritedAutoFlush(); + return isAutoFlushSet() ? autoFlush : getDefaultAutoFlush(); } - protected abstract boolean getInheritedAutoFlush(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. - * - * @since 2.3.24 + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract boolean getDefaultAutoFlush(); + @Override public boolean isAutoFlushSet() { return autoFlush != null; @@ -1027,7 +1093,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * Setter pair of {@link #getShowErrorTips()} */ public void setShowErrorTips(boolean showTips) { - showErrorTips = Boolean.valueOf(showTips); + showErrorTips = showTips; } /** @@ -1038,18 +1104,25 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetShowErrorTips() { + showErrorTips = null; + } + @Override public boolean getShowErrorTips() { - return isShowErrorTipsSet() ? showErrorTips : getInheritedShowErrorTips(); + return isShowErrorTipsSet() ? showErrorTips : getDefaultShowErrorTips(); } - protected abstract boolean getInheritedShowErrorTips(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract boolean getDefaultShowErrorTips(); + @Override public boolean isShowErrorTipsSet() { return showErrorTips != null; @@ -1070,25 +1143,46 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces return self(); } + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetAPIBuiltinEnabled() { + apiBuiltinEnabled = null; + } + @Override public boolean getAPIBuiltinEnabled() { - return isAPIBuiltinEnabledSet() ? apiBuiltinEnabled : getInheritedAPIBuiltinEnabled(); + return isAPIBuiltinEnabledSet() ? apiBuiltinEnabled : getDefaultAPIBuiltinEnabled(); } - protected abstract boolean getInheritedAPIBuiltinEnabled(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. - * - * @since 2.3.24 + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract boolean getDefaultAPIBuiltinEnabled(); + @Override public boolean isAPIBuiltinEnabledSet() { return apiBuiltinEnabled != null; } + @Override + public boolean getLogTemplateExceptions() { + return isLogTemplateExceptionsSet() ? logTemplateExceptions : getDefaultLogTemplateExceptions(); + } + + /** + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. + */ + protected abstract boolean getDefaultLogTemplateExceptions(); + + @Override + public boolean isLogTemplateExceptionsSet() { + return logTemplateExceptions != null; + } + /** * Setter pair of {@link #getLogTemplateExceptions()} */ @@ -1096,29 +1190,32 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces logTemplateExceptions = value; } - @Override - public boolean getLogTemplateExceptions() { - return isLogTemplateExceptionsSet() ? logTemplateExceptions : getInheritedLogTemplateExceptions(); + /** + * Fluent API equivalent of {@link #setLogTemplateExceptions(boolean)} + */ + public SelfT logTemplateExceptions(boolean value) { + setLogTemplateExceptions(value); + return self(); } - protected abstract boolean getInheritedLogTemplateExceptions(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). */ - @Override - public boolean isLogTemplateExceptionsSet() { - return logTemplateExceptions != null; + public void unsetLogTemplateExceptions() { + logTemplateExceptions = null; } - + @Override public boolean getLazyImports() { - return isLazyImportsSet() ? lazyImports : getInheritedLazyImports(); + return isLazyImportsSet() ? lazyImports : getDefaultLazyImports(); } - protected abstract boolean getInheritedLazyImports(); + /** + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. + */ + protected abstract boolean getDefaultLazyImports(); /** * Setter pair of {@link #getLazyImports()} @@ -1128,21 +1225,36 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Fluent API equivalent of {@link #setLazyImports(boolean)} */ + public SelfT lazyImports(boolean lazyImports) { + setLazyImports(lazyImports); + return self(); + } + + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetLazyImports() { + this.lazyImports = null; + } + @Override public boolean isLazyImportsSet() { return lazyImports != null; } - + @Override public Boolean getLazyAutoImports() { - return isLazyAutoImportsSet() ? lazyAutoImports : getInheritedLazyAutoImports(); + return isLazyAutoImportsSet() ? lazyAutoImports : getDefaultLazyAutoImports(); } - protected abstract Boolean getInheritedLazyAutoImports(); + /** + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. + */ + protected abstract Boolean getDefaultLazyAutoImports(); /** * Setter pair of {@link #getLazyAutoImports()} @@ -1151,12 +1263,24 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces this.lazyAutoImports = lazyAutoImports; lazyAutoImportsSet = true; } - + /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Fluent API equivalent of {@link #setLazyAutoImports(Boolean)} */ + public SelfT lazyAutoImports(Boolean lazyAutoImports) { + setLazyAutoImports(lazyAutoImports); + return self(); + } + + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetLazyAutoImports() { + lazyAutoImports = null; + lazyAutoImportsSet = false; + } + @Override public boolean isLazyAutoImportsSet() { return lazyAutoImportsSet; @@ -1219,21 +1343,34 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces addAutoImport((String) key, (String) value); } } - + + /** + * Fluent API equivalent of {@link #setAutoImports(Map)} + */ + public SelfT autoImports(Map map) { + setAutoImports(map); + return self(); + } + + /** + * Resets the setting value as if it was never set (but it doesn't affect the value inherited from another + * {@link ProcessingConfiguration}). + */ + public void unsetAutoImports() { + autoImports = null; + } + @Override public Map<String, String> getAutoImports() { - return isAutoImportsSet() ? autoImports : getInheritedAutoImports(); + return isAutoImportsSet() ? autoImports : getDefaultAutoImports(); } - protected abstract Map<String,String> getInheritedAutoImports(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. - * - * @since 2.3.25 + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract Map<String,String> getDefaultAutoImports(); + @Override public boolean isAutoImportsSet() { return autoImports != null; @@ -1274,18 +1411,25 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } } + /** + * Fluent API equivalent of {@link #setAutoIncludes(List)} + */ + public SelfT autoIncludes(List templateNames) { + setAutoIncludes(templateNames); + return self(); + } + @Override public List<String> getAutoIncludes() { - return isAutoIncludesSet() ? autoIncludes : getInheritedAutoIncludes(); + return isAutoIncludesSet() ? autoIncludes : getDefaultAutoIncludes(); } - protected abstract List<String> getInheritedAutoIncludes(); - /** - * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading - * the setting might returns a default value, or returns the value of the setting from a parent processing - * configuration or throws a {@link SettingValueNotSetException}. + * Returns the value the getter method returns when the setting is not set (possibly by inheriting the setting value + * from another {@link ProcessingConfiguration}), or throws {@link SettingValueNotSetException}. */ + protected abstract List<String> getDefaultAutoIncludes(); + @Override public boolean isAutoIncludesSet() { return autoIncludes != null; @@ -1402,22 +1546,22 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * <br>String value: {@code "true"}, {@code "false"}, {@code "y"}, etc. * * <li><p>{@code "auto_import"}: - * See {@link Configuration#setAutoImports(Map)} + * See {@link Configuration#getAutoImports()} * <br>String value is something like: * <br>{@code /lib/form.ftl as f, /lib/widget as w, "/lib/odd name.ftl" as odd} * * <li><p>{@code "auto_include"}: Sets the list of auto-includes. - * See {@link Configuration#setAutoIncludes(List)} + * See {@link Configuration#getAutoIncludes()} * <br>String value is something like: * <br>{@code /include/common.ftl, "/include/evil name.ftl"} * * <li><p>{@code "lazy_auto_imports"}: - * See {@link Configuration#setLazyAutoImports(Boolean)}. + * See {@link Configuration#getLazyAutoImports()}. * <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"}, * {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}), case insensitive. Also can be {@code "null"}. * <li><p>{@code "lazy_imports"}: - * See {@link Configuration#setLazyImports(boolean)}. + * See {@link Configuration#getLazyImports()}. * <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"}, * {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}), case insensitive. * @@ -1490,43 +1634,43 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * <p>{@link Configuration} (a subclass of {@link MutableProcessingConfiguration}) also understands these:</p> * <ul> * <li><p>{@code "auto_escaping"}: - * See {@link Configuration#setAutoEscapingPolicy(int)} + * See {@link Configuration#getAutoEscapingPolicy()} * <br>String value: {@code "enable_if_default"} or {@code "enableIfDefault"} for - * {@link Configuration#ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}, + * {@link ParsingConfiguration#ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}, * {@code "enable_if_supported"} or {@code "enableIfSupported"} for - * {@link Configuration#ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY} - * {@code "disable"} for {@link Configuration#DISABLE_AUTO_ESCAPING_POLICY}. + * {@link ParsingConfiguration#ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY} + * {@code "disable"} for {@link ParsingConfiguration#DISABLE_AUTO_ESCAPING_POLICY}. * * <li><p>{@code "sourceEncoding"}: - * See {@link Configuration#setSourceEncoding(Charset)}; since 2.3.26 also accepts value "JVM default" + * See {@link Configuration#getSourceEncoding()}; since 2.3.26 also accepts value "JVM default" * (not case sensitive) to set the Java environment default value. * <br>As the default value is the system default, which can change * from one server to another, <b>you should always set this!</b> * * <li><p>{@code "localized_lookup"}: - * See {@link Configuration#setLocalizedLookup}. + * See {@link Configuration#getLocalizedLookup()}. * <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"}, * {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}). * ASTDirCase insensitive. * * <li><p>{@code "output_format"}: - * See {@link Configuration#setOutputFormat(OutputFormat)}. + * See {@link ParsingConfiguration#getOutputFormat()}. * <br>String value: {@code "default"} (case insensitive) for the default, or an * <a href="#fm_obe">object builder expression</a> that gives an {@link OutputFormat}, for example * {@code HTMLOutputFormat} or {@code XMLOutputFormat}. * * <li><p>{@code "registered_custom_output_formats"}: - * See {@link Configuration#setRegisteredCustomOutputFormats(Collection)}. + * See {@link Configuration#getRegisteredCustomOutputFormats()}. * <br>String value: an <a href="#fm_obe">object builder expression</a> that gives a {@link List} of * {@link OutputFormat}-s. * Example: {@code [com.example.MyOutputFormat(), com.example.MyOtherOutputFormat()]} * * <li><p>{@code "whitespace_stripping"}: - * See {@link Configuration#setWhitespaceStripping}. + * See {@link ParsingConfiguration#getWhitespaceStripping()}. * <br>String value: {@code "true"}, {@code "false"}, {@code yes}, etc. * * <li><p>{@code "cache_storage"}: - * See {@link Configuration#setCacheStorage}. + * See {@link Configuration#getCacheStorage()}. * <br>String value: If the value contains dot, then it's interpreted as an <a href="#fm_obe">object builder * expression</a>. * If the value does not contain dot, @@ -1549,48 +1693,48 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * * <li><p>{@code "template_update_delay"}: * Template update delay in <b>seconds</b> (not in milliseconds) if no unit is specified; see - * {@link Configuration#setTemplateUpdateDelayMilliseconds(long)} for more. + * {@link Configuration#getTemplateUpdateDelayMilliseconds()} for more. * <br>String value: Valid positive integer, optionally followed by a time unit (recommended). The default * unit is seconds. It's strongly recommended to specify the unit for clarity, like in "500 ms" or "30 s". * Supported units are: "s" (seconds), "ms" (milliseconds), "m" (minutes), "h" (hours). The whitespace between * the unit and the number is optional. Units are only supported since 2.3.23. * * <li><p>{@code "tag_syntax"}: - * See {@link Configuration#setTagSyntax(int)}. + * See {@link ParsingConfiguration#getTagSyntax()}. * <br>String value: Must be one of * {@code "auto_detect"}, {@code "angle_bracket"}, and {@code "square_bracket"}. * * <li><p>{@code "naming_convention"}: - * See {@link Configuration#setNamingConvention(int)}. + * See {@link ParsingConfiguration#getNamingConvention()}. * <br>String value: Must be one of * {@code "auto_detect"}, {@code "legacy"}, and {@code "camel_case"}. * * <li><p>{@code "incompatible_improvements"}: - * See {@link Configuration#setIncompatibleImprovements(Version)}. + * See {@link Configuration#getIncompatibleImprovements()}. * <br>String value: version number like {@code 2.3.20}. * * <li><p>{@code "recognize_standard_file_extensions"}: - * See {@link Configuration#setRecognizeStandardFileExtensions(boolean)}. + * See {@link Configuration#getRecognizeStandardFileExtensions()}. * <br>String value: {@code "default"} (case insensitive) for the default, or {@code "true"}, {@code "false"}, * {@code yes}, etc. * * <li><p>{@code "template_configurations"}: - * See: {@link Configuration#setTemplateConfigurations(org.apache.freemarker.core.templateresolver.TemplateConfigurationFactory)}. + * See: {@link Configuration#getTemplateConfigurations()}. * <br>String value: Interpreted as an <a href="#fm_obe">object builder expression</a>, * can be {@code null}. * * <li><p>{@code "template_loader"}: - * See: {@link Configuration#setTemplateLoader(TemplateLoader)}. + * See: {@link Configuration#getTemplateLoader()}. * <br>String value: {@code "default"} (case insensitive) for the default, or else interpreted as an * <a href="#fm_obe">object builder expression</a>. {@code "null"} is also allowed. * * <li><p>{@code "template_lookup_strategy"}: - * See: {@link Configuration#setTemplateLookupStrategy(org.apache.freemarker.core.templateresolver.TemplateLookupStrategy)}. + * See: {@link Configuration#getTemplateLookupStrategy()}. * <br>String value: {@code "default"} (case insensitive) for the default, or else interpreted as an * <a href="#fm_obe">object builder expression</a>. * * <li><p>{@code "template_name_format"}: - * See: {@link Configuration#setTemplateNameFormat(org.apache.freemarker.core.templateresolver.TemplateNameFormat)}. + * See: {@link Configuration#getTemplateNameFormat()}. * <br>String value: {@code "default"} (case insensitive) for the default, {@code "default_2_3_0"} * for {@link DefaultTemplateNameFormatFM2#INSTANCE}, {@code "default_2_4_0"} for * {@link DefaultTemplateNameFormat#INSTANCE}. @@ -1743,8 +1887,9 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } else if ("rethrow".equalsIgnoreCase(value)) { setTemplateExceptionHandler( TemplateExceptionHandler.RETHROW_HANDLER); - } else if (DEFAULT_VALUE.equalsIgnoreCase(value) && this instanceof Configuration) { - ((Configuration) this).unsetTemplateExceptionHandler(); + } else if (DEFAULT_VALUE.equalsIgnoreCase(value) + && this instanceof Configuration.ExtendableBuilder) { + unsetTemplateExceptionHandler(); } else { throw new ConfigurationSettingValueException( name, value, @@ -1770,12 +1915,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } } else if (OBJECT_WRAPPER_KEY_SNAKE_CASE.equals(name) || OBJECT_WRAPPER_KEY_CAMEL_CASE.equals(name)) { if (DEFAULT_VALUE.equalsIgnoreCase(value)) { - if (this instanceof Configuration) { - ((Configuration) this).unsetObjectWrapper(); + if (this instanceof Configuration.ExtendableBuilder) { + this.unsetObjectWrapper(); } else { - setObjectWrapper(Configuration.getDefaultObjectWrapper(Configuration.VERSION_3_0_0)); + // FM3 TODO should depend on IcI + setObjectWrapper(new DefaultObjectWrapper.Builder(Configuration.VERSION_3_0_0).build()); } } else if ("restricted".equalsIgnoreCase(value)) { + // FM3 TODO should depend on IcI setObjectWrapper(new RestrictedObjectWrapper.Builder(Configuration.VERSION_3_0_0).build()); } else { setObjectWrapper((ObjectWrapper) _ObjectBuilderSettingEvaluator.eval( @@ -1857,6 +2004,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } /** + * Fluent API equivalent of {@link #setSetting(String, String)}. + */ + public SelfT setting(String name, String value) throws ConfigurationException { + setSetting(name, value); + return self(); + } + + /** * @throws IllegalArgumentException * if the type of the some of the values isn't as expected */ @@ -1879,11 +2034,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces * If we want the setting names with camel case naming convention, or with snake case (legacy) naming * convention. * - * @see Configuration#getSettingNames(boolean) + * @see Configuration.ExtendableBuilder#getSettingNames(boolean) * * @since 2.3.24 */ - public Set<String> getSettingNames(boolean camelCase) { + public static Set<String> getSettingNames(boolean camelCase) { return new _SortedArraySet<>(camelCase ? SETTING_NAMES_CAMEL_CASE : SETTING_NAMES_SNAKE_CASE); } @@ -1945,11 +2100,21 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } } + /** + * Fluent API equivalent of {@link #setSettings(Properties)}. + */ + public SelfT settings(Properties props) { + setSettings(props); + return self(); + } + @Override public Map<Object, Object> getCustomAttributes() { - return customAttributes; + return isCustomAttributesSet() ? customAttributes : getDefaultCustomAttributes(); } + protected abstract Map<Object,Object> getDefaultCustomAttributes(); + /** * Setter pair of {@link #getCustomAttributes()} * @@ -1960,6 +2125,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } /** + * Fluent API equivalent of {@link #setCustomAttributes(Map)} + */ + public SelfT customAttributes(Map<Object, Object> customAttributes) { + setCustomAttributes(customAttributes); + return self(); + } + + /** * Used internally instead of {@link #setCustomAttributes(Map)} to speed up use cases where we know that there * won't be aliasing problems. */ @@ -1995,6 +2168,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } /** + * Fluent API equivalent of {@link #setCustomAttribute(Object, Object)} + */ + public SelfT customAttribute(Object name, Object value) { + setCustomAttribute(name, value); + return self(); + } + + /** * Returns an array with names of all custom attributes defined directly on this {@link ProcessingConfiguration}. * (That is, it doesn't contain the names of custom attributes inherited from other {@link * ProcessingConfiguration}-s.) The returned array is never {@code null}, but can be zero-length. @@ -2043,10 +2224,10 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces } else { value = null; } - return value != null ? value : getInheritedCustomAttribute(key); + return value != null ? value : getDefaultCustomAttribute(key); } - protected abstract Object getInheritedCustomAttribute(Object name); + protected abstract Object getDefaultCustomAttribute(Object name); protected final List<String> parseAsList(String text) throws GenericParseException { return new SettingStringParser(text).parseAsList();
