blob: 2410e87a1566e012686c7d3b506dc1b987432dc1 [file] [log] [blame]
/*
* 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;
import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
import org.apache.freemarker.core.arithmetic.impl.BigDecimalArithmeticEngine;
import org.apache.freemarker.core.cformat.CFormat;
import org.apache.freemarker.core.cformat.impl.JavaScriptOrJSONCFormat;
import org.apache.freemarker.core.model.ObjectWrapper;
import org.apache.freemarker.core.model.impl.MemberAccessPolicy;
import org.apache.freemarker.core.pluggablebuiltin.TruncateBuiltinAlgorithm;
import org.apache.freemarker.core.pluggablebuiltin.impl.DefaultTruncateBuiltinAlgorithm;
import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
import org.apache.freemarker.core.valueformat.TemplateNumberFormat;
import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
import java.io.Serializable;
import java.io.Writer;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Implemented by FreeMarker core classes (not by you) that provide configuration settings that affect {@linkplain
* Template#process(Object, Writer) template processing} (as opposed to template parsing). <b>New methods may be added
* any time in future FreeMarker versions, so don't try to implement this interface yourself!</b>
*
* @see ParsingConfiguration
* @see ParsingAndProcessingConfiguration
*/
public interface ProcessingConfiguration {
/**
* Useful as the default value parameter to {#getCustomSetting(Serializable, Object)}, because this value is not
* allowed for custom settings.
*/
Object MISSING_VALUE_MARKER = new Object();
/**
* The locale used for number and date formatting (among others), also the locale used for searching localized
* template variations when no locale was explicitly specified where the template is requested.
*
* @see Configuration#getTemplate(String, Locale)
*/
Locale getLocale();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isLocaleSet();
/**
* The time zone to use when formatting date/time values. It {@link Configuration}-level default
* is the system time zone ({@link TimeZone#getDefault()}), regardless of the "locale" FreeMarker setting,
* so in a server application you probably want to set it explicitly in the {@link Environment} to match the
* preferred time zone of the target audience (like the Web page visitor).
*
* <p>If you or the templates set the time zone, you should probably also set
* {@link #getSQLDateAndTimeTimeZone()}!
*
* @see #getSQLDateAndTimeTimeZone()
*/
TimeZone getTimeZone();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isTimeZoneSet();
/**
* The time zone used when dealing with {@link java.sql.Date java.sql.Date} and
* {@link java.sql.Time java.sql.Time} values. Its {@link Configuration}-level defaults is
* {@link TimeZone#getDefault()}, that is, the JVM default time zone (server default time zone), because that's
* what most JDBC drivers will use when constructing the {@link java.sql.Date java.sql.Date} and
* {@link java.sql.Time java.sql.Time} values. If this setting is {@code null} FreeMarker will use the value of
* ({@link #getTimeZone()}) for {@link java.sql.Date java.sql.Date} and {@link java.sql.Time java.sql.Time}
* values, which often gives bad results due to how most JDBC drivers work.
*
* <p>This setting doesn't influence the formatting of other kind of values (like of
* {@link java.sql.Timestamp java.sql.Timestamp} or plain {@link java.util.Date java.util.Date} values).
*
* <p>To decide what value you need, a few things has to be understood:
* <ul>
* <li>Date-only and time-only values in SQL-oriented databases are usually store calendar and clock field
* values directly (year, month, day, or hour, minute, seconds (with decimals)), as opposed to a set of points
* on the physical time line. Thus, unlike SQL timestamps, these values usually aren't meant to be shown
* differently depending on the time zone of the audience.
*
* <li>When a JDBC query has to return a date-only or time-only value, it has to convert it to a point on the
* physical time line, because that's what {@link java.util.Date} and its subclasses store (milliseconds since
* the epoch). Obviously, this is impossible to do. So JDBC just chooses a physical time which, when rendered
* <em>with the JVM default time zone</em>, will give the same field values as those stored
* in the database. (Actually, you can give JDBC a calendar, and so it can use other time zones too, but most
* application won't care using those overloads.) For example, assume that the system time zone is GMT+02:00.
* Then, 2014-07-12 in the database will be translated to physical time 2014-07-11 22:00:00 UTC, because that
* rendered in GMT+02:00 gives 2014-07-12 00:00:00. Similarly, 11:57:00 in the database will be translated to
* physical time 1970-01-01 09:57:00 UTC. Thus, the physical time stored in the returned value depends on the
* default system time zone of the JDBC client, not just on the content of the database. (This used to be the
* default behavior of ORM-s, like Hibernate, too.)
*
* <li>The value of the {@code timeZone} FreeMarker configuration setting sets the time zone used for the
* template output. For example, when a web page visitor has a preferred time zone, the web application framework
* may calls {@link Environment#setTimeZone(TimeZone)} with that time zone. Thus, the visitor will
* see {@link java.sql.Timestamp java.sql.Timestamp} and plain {@link java.util.Date java.util.Date} values as
* they look in his own time zone. While
* this is desirable for those types, as they meant to represent physical points on the time line, this is not
* necessarily desirable for date-only and time-only values. When {@code sqlDateAndTimeTimeZone} is
* {@code null}, {@code timeZone} is used for rendering all kind of date/time/dateTime values, including
* {@link java.sql.Date java.sql.Date} and {@link java.sql.Time java.sql.Time}, and then if, for example,
* {@code timeZone} is GMT+00:00, the
* values from the earlier examples will be shown as 2014-07-11 (one day off) and 09:57:00 (2 hours off). While
* those are the time zone correct renderings, those values are probably meant to be shown "as is".
*
* <li>You may wonder why this setting isn't simply "SQL time zone", that is, why's this time zone not applied to
* {@link java.sql.Timestamp java.sql.Timestamp} values as well. Timestamps in databases refer to a point on
* the physical time line, and thus doesn't have the inherent problem of date-only and time-only values.
* FreeMarker assumes that the JDBC driver converts time stamps coming from the database so that they store
* the distance from the epoch (1970-01-01 00:00:00 UTC), as requested by the {@link java.util.Date} API.
* Then time stamps can be safely rendered in different time zones, and thus need no special treatment.
* </ul>
*
* @see #getTimeZone()
*/
TimeZone getSQLDateAndTimeTimeZone();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isSQLDateAndTimeTimeZoneSet();
/**
* The number format used to convert numbers to strings (where no number format is explicitly given). Its
* {@link Configuration}-level default is {@code "number"}. The possible values are:
* <ul>
* <li>{@code "number"}: The number format returned by {@link NumberFormat#getNumberInstance(Locale)}</li>
* <li>{@code "c"}: The number format used by FTL's {@code c} built-in (like in
* {@code someNumber?c}). So with this <code>${someNumber}</code> will output the same as
* <code>${someNumber?c}</code>. This should only be used if the template solely generates source code,
* configuration file, or other content that's not read by normal users. If the template contains parts that's
* read by normal users (like typical a web page), you are not supposed to use this.</li>
* <li>{@code "currency"}: The number format returned by {@link NumberFormat#getCurrencyInstance(Locale)}</li>
* <li>{@code "percent"}: The number format returned by {@link NumberFormat#getPercentInstance(Locale)}</li>
* <li>A {@link java.text.DecimalFormat} pattern (like {@code "0.##"}). This syntax is extended by FreeMarker
* so that you can specify options like the rounding mode and the symbols used after a 2nd semicolon. For
* example, {@code ",000;; roundingMode=halfUp groupingSeparator=_"} will format numbers like {@code ",000"}
* would, but with half-up rounding mode, and {@code _} as the group separator. See more about "extended Java
* decimal format" in the FreeMarker Manual.
* </li>
* <li>If the string starts with {@code @} character followed by a letter then it's interpreted as a custom number
* format. The format of a such string is <code>"@<i>name</i>"</code> or <code>"@<i>name</i>
* <i>parameters</i>"</code>, where <code><i>name</i></code> is the key in the {@link Map} set by
* {@link MutableProcessingConfiguration#setCustomNumberFormats(Map)}, and <code><i>parameters</i></code> is
* parsed by the custom {@link TemplateNumberFormat}.
* </li>
* </ul>
*/
String getNumberFormat();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isNumberFormatSet();
/**
* A {@link Map} that associates {@link TemplateNumberFormatFactory}-es to names, which then can be referred by the
* {@link #getNumberFormat() numberFormat} setting with values starting with <code>@<i>name</i></code>. The keys in
* the {@link Map} should start with an UNICODE letter, and should only contain UNICODE letters and digits (not
* {@code _}), otherwise accessing the custom format from templates can be difficult or impossible. The
* {@link Configuration}-level default of this setting is an empty {@link Map}.
* <p>
* When the {@link ProcessingConfiguration} is part of a setting inheritance chain ({@link Environment} inherits
* settings from the main {@link Template}, which inherits from the {@link Configuration}), you still only get the
* {@link Map} from the closest {@link ProcessingConfiguration} where it was set, not a {@link Map} that respects
* inheritance. Thus, to get a custom format you shouldn't use this {@link Map} directly, but
* {@link #getCustomNumberFormat(String)}, which will search the format in the inheritance chain.
*
* @return Never {@code null}; unmodifiable {@link Map}.
*/
Map<String, TemplateNumberFormatFactory> getCustomNumberFormats();
/**
* Gets the custom number format registered for the name. This differs from calling {@link #getCustomNumberFormats()
* getCustomNumberFormats().get(name)}, because if there's {@link ProcessingConfiguration} from which setting values
* are inherited then this method will search the custom format there as well if it isn't found here. For example,
* {@link Environment#getCustomNumberFormat(String)} will check if the {@link Environment} contains the custom
* format with the name, and if not, it will try {@link Template#getCustomNumberFormat(String)} on the main
* template, which in turn might falls back to calling {@link Configuration#getCustomNumberFormat(String)}.
*/
TemplateNumberFormatFactory getCustomNumberFormat(String name);
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isCustomNumberFormatsSet();
/**
* The string value for the boolean {@code true} and {@code false} values, usually intended for human consumption
* (not for a computer language), separated with comma. For example, {@code "yes,no"}. Note that white-space is
* significant, so {@code "yes, no"} is WRONG (unless you want that leading space before "no"). Because the proper
* way of formatting booleans depends on the context too much, it's probably the best to leave this setting on its
* default, {@code ""}, which will enforce explicit formatting, like <code>${aBoolean?string('on', 'off')}</code>.
*
* <p>If you generate the piece of output for "computer audience" as opposed to "human audience", then you should
* write <code>${myBoolean?c}</code>, which will print {@code true} or {@code false}. If you really want to always
* format for computer audience, then it's might be reasonable to set this setting to {@code c}.
*/
String getBooleanFormat();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isBooleanFormatSet();
/**
* The format used to convert {@link java.util.Date}-s that are time (no date part) values to string-s, also the
* format that {@code someString?time} will use to parse strings.
*
* <p>For the possible values see {@link #getDateTimeFormat()}.
*
* <p>Its {@link Configuration}-level default is {@code ""}, which is equivalent to {@code "medium"}.
*/
String getTimeFormat();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isTimeFormatSet();
/**
* The format used to convert {@link java.util.Date}-s that are date-only (no time part) values to string-s,
* also the format that {@code someString?date} will use to parse strings.
*
* <p>For the possible values see {@link #getDateTimeFormat()}.
*
* <p>Its {@link Configuration}-level default is {@code ""} which is equivalent to {@code "medium"}.
*/
String getDateFormat();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isDateFormatSet();
/**
* The format used to convert {@link java.util.Date}-s that are date-time (timestamp) values to string-s,
* also the format that {@code someString?dateTime} will use to parse strings.
*
* <p>The possible setting values are (the quotation marks aren't part of the value itself):
*
* <ul>
* <li><p>Patterns accepted by Java's {@link SimpleDateFormat}, for example {@code "dd.MM.yyyy HH:mm:ss"} (where
* {@code HH} means 24 hours format) or {@code "MM/dd/yyyy hh:mm:ss a"} (where {@code a} prints AM or PM, if
* the current language is English).
*
* <li><p>{@code "xs"} for XML Schema format, or {@code "iso"} for ISO 8601:2004 format.
* These formats allow various additional options, separated with space, like in
* {@code "iso m nz"} (or with {@code _}, like in {@code "iso_m_nz"}; this is useful in a case like
* {@code lastModified?string.iso_m_nz}). The options and their meanings are:
*
* <ul>
* <li><p>Accuracy options:<br>
* {@code ms} = Milliseconds, always shown with all 3 digits, even if it's all 0-s.
* Example: {@code 13:45:05.800}<br>
* {@code s} = Seconds (fraction seconds are dropped even if non-0), like {@code 13:45:05}<br>
* {@code m} = Minutes, like {@code 13:45}. This isn't allowed for "xs".<br>
* {@code h} = Hours, like {@code 13}. This isn't allowed for "xs".<br>
* Neither = Up to millisecond accuracy, but trailing millisecond 0-s are removed, also the whole
* milliseconds part if it would be 0 otherwise. Example: {@code 13:45:05.8}
*
* <li><p>Time zone offset visibility options:<br>
* {@code fz} = "Force Zone", always show time zone offset (even for for
* {@link java.sql.Date java.sql.Date} and {@link java.sql.Time java.sql.Time} values).
* But, because ISO 8601 doesn't allow for dates (means date without time of the day) to
* show the zone offset, this option will have no effect in the case of {@code "iso"} with
* dates.<br>
* {@code nz} = "No Zone", never show time zone offset<br>
* Neither = always show time zone offset, except for {@link java.sql.Date java.sql.Date}
* and {@link java.sql.Time java.sql.Time}, and for {@code "iso"} date values.
*
* <li><p>Time zone options:<br>
* {@code u} = Use UTC instead of what the {@code timeZone} setting suggests. However,
* {@link java.sql.Date java.sql.Date} and {@link java.sql.Time java.sql.Time} aren't affected
* by this (see {@link #getSQLDateAndTimeTimeZone()} to understand why)<br>
* {@code fu} = "Force UTC", that is, use UTC instead of what the {@code timeZone} or the
* {@code sqlDateAndTimeTimeZone} setting suggests. This also effects
* {@link java.sql.Date java.sql.Date} and {@link java.sql.Time java.sql.Time} values<br>
* Neither = Use the time zone suggested by the {@code timeZone} or the
* {@code sqlDateAndTimeTimeZone} configuration setting ({@link #getTimeZone()} and
* {@link #getSQLDateAndTimeTimeZone()}).
* </ul>
*
* <p>The options can be specified in any order.</p>
*
* <p>Options from the same category are mutually exclusive, like using {@code m} and {@code s}
* together is an error.
*
* <p>The accuracy and time zone offset visibility options don't influence parsing, only formatting.
* For example, even if you use "iso m nz", "2012-01-01T15:30:05.125+01" will be parsed successfully and with
* milliseconds accuracy.
* The time zone options (like "u") influence what time zone is chosen only when parsing a string that doesn't
* contain time zone offset.
*
* <p>Parsing with {@code "iso"} understands both extend format and basic format, like
* {@code 20141225T235018}. It doesn't, however, support the parsing of all kind of ISO 8601 strings: if
* there's a date part, it must use year, month and day of the month values (not week of the year), and the
* day can't be omitted.
*
* <p>The output of {@code "iso"} is deliberately so that it's also a good representation of the value with
* XML Schema format, except for 0 and negative years, where it's impossible. Also note that the time zone
* offset is omitted for date values in the {@code "iso"} format, while it's preserved for the {@code "xs"}
* format.
*
* <li><p>{@code "short"}, {@code "medium"}, {@code "long"}, or {@code "full"}, which that has locale-dependent
* meaning defined by the Java platform (see in the documentation of {@link java.text.DateFormat}).
* For date-time values, you can specify the length of the date and time part independently, be separating
* them with {@code _}, like {@code "short_medium"}. ({@code "medium"} means
* {@code "medium_medium"} for date-time values.)
*
* <li><p>Anything that starts with {@code "@"} followed by a letter is interpreted as a custom
* date/time/dateTime format, but only if either {@link Configuration#getIncompatibleImprovements()}
* is at least 2.3.24, or there's any custom formats defined (even if custom number format). The format of
* such string is <code>"@<i>name</i>"</code> or <code>"@<i>name</i> <i>parameters</i>"</code>, where
* <code><i>name</i></code> is the name parameter to {@link #getCustomDateFormat(String)}, and
* <code><i>parameters</i></code> is parsed by the custom number format.
*
* </ul>
*
* <p>Its {@link Configuration}-level default is {@code ""}, which is equivalent to {@code "medium_medium"}.
*/
String getDateTimeFormat();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isDateTimeFormatSet();
/**
* A {@link Map} that associates {@link TemplateDateFormatFactory}-es to names, which then can be referred by the
* {@link #getDateFormat() dateFormat}/{@link #getDateFormat() dateFormat }/{@link #getDateTimeFormat()
* dateTimeFormat} settings with values starting with <code>@<i>name</i></code>. The keys in the {@link Map} should
* start with an UNICODE letter, and should only contain UNICODE letters and digits (not {@code _}), otherwise
* accessing the custom format from templates can be difficult or impossible. The {@link Configuration}-level
* default of this setting is an empty {@link Map}.
* <p>
* When the {@link ProcessingConfiguration} is part of a setting inheritance chain ({@link Environment} inherits
* settings from the main {@link Template}, which inherits from the {@link Configuration}), you still only get the
* {@link Map} from the closest {@link ProcessingConfiguration} where it was set, not a {@link Map} that respects
* inheritance. Thus, to get a custom format you shouldn't use this {@link Map} directly, but {@link
* #getCustomDateFormat(String)}, which will search the format in the inheritance chain.
*
* @return Never {@code null}; unmodifiable {@link Map}.
*/
Map<String, TemplateDateFormatFactory> getCustomDateFormats();
/**
* Gets the custom date or time or date-time format registered for the name. This differs from calling {@link
* #getCustomDateFormats() getCustomDateFormats.get(name)}, because if there's {@link ProcessingConfiguration} from
* which setting values are inherited then this method will search the custom format there as well if it isn't found
* here. For example, {@link Environment#getCustomNumberFormat(String)} will check if the {@link Environment}
* contains the custom format with the name, and if not, it will try {@link Template#getCustomDateFormat(String)} on
* the main template, which in turn might falls back to calling {@link Configuration#getCustomDateFormat(String)}.
*/
TemplateDateFormatFactory getCustomDateFormat(String name);
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isCustomDateFormatsSet();
/**
* The format (usually a computer language) used {@code ?c}, {@code ?cn}, and for the
* {@code "c"} {@link #getNumberFormat() numberFormat}, and the
* {@code "c"} {@link #getBooleanFormat() booleanFormat}.
* Its {@link Configuration}-level default is {@link JavaScriptOrJSONCFormat#INSTANCE "JavaScript or JSON"}.
*/
CFormat getCFormat();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isCFormatSet();
/**
* The exception handler used to handle exceptions occurring inside templates.
* Its {@link Configuration}-level default is {@link TemplateExceptionHandler#RETHROW}. The recommended
* values are:
*
* <ul>
* <li>In production systems: {@link TemplateExceptionHandler#RETHROW}
* <li>During development of HTML templates, if you want to the error directly in the browser:
* {@link TemplateExceptionHandler#HTML_DEBUG}
* <li>During development of non-HTML templates, if you want to the error directly in the output:
* {@link TemplateExceptionHandler#DEBUG}
* </ul>
*
* <p>All of these will let the exception propagate further, so that you can catch it around
* {@link Template#process(Object, Writer)} for example. The difference is in what they print on the output before
* they do that.
*
* <p>Note that the {@link TemplateExceptionHandler} is not meant to be used for generating HTTP error pages.
* Neither is it meant to be used to roll back the printed output. These should be solved outside template
* processing when the exception raises from {@link Template#process(Object, Writer) Template.process}.
* {@link TemplateExceptionHandler} meant to be used if you want to include special content <em>in</em> the template
* output, or if you want to suppress certain exceptions. If you suppress an exception then it's the responsibility
* of the {@link TemplateExceptionHandler} to log the exception (if you want it to be logged).
*
* @see #getAttemptExceptionReporter()
*/
TemplateExceptionHandler getTemplateExceptionHandler();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isTemplateExceptionHandlerSet();
/**
* Specifies how exceptions handled (and hence suppressed) by an {@code #attempt} blocks will be logged or otherwise
* reported. The default value is {@link AttemptExceptionReporter#LOG_ERROR}.
*
* <p>Note that {@code #attempt} is not supposed to be a general purpose error handler mechanism, like {@code try}
* is in Java. It's for decreasing the impact of unexpected errors, by making it possible that only part of the
* page is going down, instead of the whole page. But it's still an error, something that someone should fix. So the
* error should be reported, not just ignored in a custom {@link AttemptExceptionReporter}-s.
*
* <p>The {@link AttemptExceptionReporter} is not invoked if the {@link TemplateExceptionHandler} has
* suppressed the exception.
*/
AttemptExceptionReporter getAttemptExceptionReporter();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* a {@link CoreSettingValueNotSetException}.
*/
boolean isAttemptExceptionReporterSet();
/**
* The arithmetic engine used to perform arithmetic operations.
* Its {@link Configuration}-level default is {@link BigDecimalArithmeticEngine#INSTANCE}.
* Note that this setting overlaps with {@link ParsingConfiguration#getArithmeticEngine()}.
*/
ArithmeticEngine getArithmeticEngine();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isArithmeticEngineSet();
/**
* Informs FreeMarker about the charset used for the output. As FreeMarker outputs character stream (not
* byte stream), it's not aware of the output charset unless the software that encloses it tells it
* with this setting. Some templates may use FreeMarker features that require this information.
* Setting this to {@code null} means that the output encoding is not known.
*
* <p>Its {@link Configuration}-level default is {@code null}.
*/
Charset getOutputEncoding();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isOutputEncodingSet();
/**
* The URL escaping (URL encoding, percentage encoding) charset. If ({@code null}), the output encoding
* ({@link #getOutputEncoding()}) will be used. Its {@link Configuration}-level default is {@code null}.
*/
Charset getURLEscapingCharset();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isURLEscapingCharsetSet();
/**
* The {@link TemplateClassResolver} that is used when the <code>new</code> built-in is called in a template. That
* is, when a template contains the <code>"com.example.SomeClassName"?new</code> expression, this object will be
* called to resolve the <code>"com.example.SomeClassName"</code> string to a class. The default value is {@link
* TemplateClassResolver#UNRESTRICTED}. If you allow users to upload templates, it's important to use a
* custom restrictive {@link TemplateClassResolver} or {@link TemplateClassResolver#ALLOW_NOTHING}.
*
* <p>Note that the {@link MemberAccessPolicy} used by the {@link ObjectWrapper} also influences what constructors
* are available. Allowing the resolution of the class here is not enough in itself, as the
* {@link MemberAccessPolicy} has to allow exposing the particular constructor you try to call as well.
*/
TemplateClassResolver getNewBuiltinClassResolver();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isNewBuiltinClassResolverSet();
/**
* Specifies if {@code ?api} can be used in templates. Its {@link Configuration}-level is {@code false} (which
* is the safest option).
*/
boolean getAPIBuiltinEnabled();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isAPIBuiltinEnabledSet();
/**
* Whether the output {@link Writer} is automatically flushed at the end of {@link Template#process(Object, Writer)}
* (and its overloads). Its {@link Configuration}-level default is {@code true}.
* <p>
* Using {@code false} is needed for example when a Web page is composed from several boxes (like portlets, GUI
* panels, etc.) that aren't inserted with {@code #include} (or with similar directives) into a master FreeMarker
* template, rather they are all processed with a separate {@link Template#process(Object, Writer)} call. In a such
* scenario the automatic flushes would commit the HTTP response after each box, hence interfering with full-page
* buffering, and also possibly decreasing performance with too frequent and too early response buffer flushes.
*/
boolean getAutoFlush();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isAutoFlushSet();
/**
* Whether tips should be shown in error messages of errors arising during template processing.
* Its {@link Configuration}-level default is {@code true}.
*/
boolean getShowErrorTips();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isShowErrorTipsSet();
/**
* 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
* makes the overhead of <em>unused</em> imports negligible. Note that turning on lazy importing isn't entirely
* transparent, as accessing global variables (usually created with {@code <#global ...=...>}) that should be
* created by the imported template won't trigger the loading and processing of the lazily imported template
* (because globals aren't accessed through the namespace variable), so the global variable will just be missing.
* In general, you lose the strict control over when the namespace initializing code in the imported template will
* be executed, though it shouldn't mater for most well designed imported templates.
* Another drawback is that importing a missing or otherwise broken template will be successful, and the problem
* will remain hidden until (and if) the namespace content is actually used. Note that the namespace initializing
* code will run with the same {@linkplain ProcessingConfiguration#getLocale() locale} as it was at the point of the
* {@code <#import ...>} call (other settings won't be handled specially like that).
* <p>
* The default is {@code false} (and thus imports are eager) for backward compatibility, which can cause
* perceivable overhead if you have many imports and only a few of them is actually used.
* <p>
* This setting also affects {@linkplain #getAutoImports() auto-imports}, unless you have set a non-{@code null}
* value with {@link #getLazyAutoImports()}.
*
* @see #getLazyAutoImports()
*/
boolean getLazyImports();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isLazyImportsSet();
/**
* Specifies if {@linkplain #getAutoImports() auto-imports} will be
* {@link #getLazyImports() lazy imports}. This is useful to make the overhead of <em>unused</em>
* auto-imports negligible. If this is set to {@code null}, {@link #getLazyImports()} specifies the behavior of
* auto-imports too. The default value is {@code null}.
*/
Boolean getLazyAutoImports();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isLazyAutoImportsSet();
/**
* Adds invisible <code>#import <i>templateName</i> as <i>namespaceVarName</i></code> statements at the beginning of
* the main template (that's the top-level template that wasn't included/imported from another template). While
* it only affects the main template directly, as the imports will create a global variable there, the imports
* will be visible from the further imported templates too.
* <p>
* It's recommended to set the {@link Configuration#getLazyAutoImports() lazyAutoImports} setting to {@code true}
* when using this, so that auto-imports that are unused in a template won't degrade performance by unnecessary
* loading and initializing the imported library.
* <p>
* If the imports aren't lazy, the order of the imports will be the same as the order in which the {@link Map}
* iterates through its entries.
* <p>
* When the {@link ProcessingConfiguration} is part of a setting inheritance chain ({@link Environment} inherits
* settings from the main {@link Template}, which inherits from the {@link Configuration}), you still only get the
* {@link Map} from the closest {@link ProcessingConfiguration} where it was set, not a {@link Map} that respects
* inheritance. But FreeMarker will walk the whole inheritance chain, executing all auto-imports starting
* from the ancestors. If, however, the same auto-import <code><i>namespaceVarName</i></code> occurs in multiple
* {@link ProcessingConfiguration}-s of the chain, only the one in the last (child)
* {@link ProcessingConfiguration} will be executed.
* <p>
* If there are also auto-includes (see {@link #getAutoIncludes()}), those will be executed after the auto-imports.
* <p>
* The {@link Configuration}-level default of this setting is an empty {@link Map}.
*
* @return Never {@code null}
*/
Map<String, String> getAutoImports();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isAutoImportsSet();
/**
* Adds an invisible <code>#include <i>templateName</i></code> at the beginning of the main template (that's the
* top-level template that wasn't included/imported from another template).
* <p>
* The order of the inclusions will be the same as the order in this {@link List}.
* <p>
* When the {@link ProcessingConfiguration} is part of a setting inheritance chain ({@link Environment} inherits
* settings from the main {@link Template}, which inherits from the {@link Configuration}), you still only get the
* {@link List} from the closest {@link ProcessingConfiguration} where it was set, not a {@link List} that respects
* inheritance. But FreeMarker will walk the whole inheritance chain, executing all auto-imports starting
* from the ancestors. If, however, the same auto-included template name occurs in multiple
* {@link ProcessingConfiguration}-s of the chain, only the one in the last (child)
* {@link ProcessingConfiguration} will be executed.
* <p>
* If there are also auto-imports ({@link #getAutoImports()}), those imports will be executed before
* the auto-includes, hence the namespace variables are alrady accessible for the auto-included templates.
*
* @return An unmodifiable {@link List}; not {@code null}
*/
List<String> getAutoIncludes();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
boolean isAutoIncludesSet();
/**
* Retrieves the value of a custom setting. Custom settings are key-value pairs associated to a {@link
* ProcessingConfiguration} object, that the FreeMarker core doesn't try to interpret. They are like configuration
* settings added dynamically (as opposed to in compilation time), where each custom setting is treated as an
* individual setting. So where predefined configuration settings used to have {@code isXxxSet}, {@code
* unsetXxx}, and {@code setXxx} methods, custom settings have these too, with a key (the identifier of the
* custom setting) as an extra argument (see {@link #isCustomSettingSet(Serializable)},
* {@link MutableProcessingConfiguration#setCustomSetting(Serializable, Object)},
* {@link MutableProcessingConfiguration#unsetCustomSetting(Serializable)}).
* <p>
* When the {@link ProcessingConfiguration} is part of a setting inheritance chain ({@link Environment} inherits
* settings from the main {@link Template}, which inherits from the {@link Configuration}), this method will search
* the custom setting in the whole inheritance chain, until it finds it.
* <p>
* To prevent key clashes (and for better performance), it's often a good idea to use enums as keys, rather than
* {@link String}-s. If {@link String}-s are used for keys (names) by components that will be reused on several
* places, then to avoid accidental name clashes, the names should use a prefix similar to a package name, like
* like "com.example.myframework.".
* <p>
* The values of custom settings should be immutable, or at least not changed after they were added as a
* custom setting value. To store custom state information (such as application or framework specific caches)
* you should use the methods provided by {@link CustomStateScope} instead.
* <p>
* The FreeMarker core doesn't provide any means for accessing custom settings from the templates. If a framework
* or application needs such functionality, it has to add its own custom directives/methods for that. But its
* more typical that custom settings just influence the behavior of custom directives/methods without the normal
* templates directly accessing them, or that they are just used by the framework code that invokes templates.
*
* @param key
* The identifier (usually an enum or a {@link String}) of the custom setting; not {@code null}; must be
* usable as {@link HashMap} key
*
* @return The value of the custom setting; possibly {@code null}, as that's a legal attribute value. The content
* of the value object shouldn't be changed after it was added as an attribute (ideally, it should be an
* immutable object); if you need to change the content, certainly you should use the {@link CustomStateScope}
* API. Note that if the custom setting was created with <code>&lt;#ftl&nbsp;customSettings={...}&gt;</code>, then
* this value is already unwrapped (i.e. it's a <code>String</code>, or a <code>List</code>, or a <code>Map</code>,
* ...etc., not a FreeMarker specific class).
*
* @throws CustomSettingValueNotSetException if the custom setting was not set (not even to {@code null}), nor in
* this {@link ProcessingConfiguration}, nor in another where we inherit settings from. Use
* {@link #getCustomSetting(Serializable, Object)} to avoid this exception.
*/
Object getCustomSetting(Serializable key) throws CustomSettingValueNotSetException;
/**
* Same as {@link #getCustomSetting(Serializable)}, but instead of throwing {@link CustomSettingValueNotSetException}
* it returns the default value specified as the 2nd argument.
*
* @param defaultValue
* The value to return if the attribute is not set. Note that an attribute that was explicitly set to
* {@code null}, then {@code null} will be returned for it, not the default value specified here, since
* the attribute was set. If you want to know if the value was set, {@link #MISSING_VALUE_MARKER} can
* be used, as it's guaranteed that an attribute never has that value.
*/
Object getCustomSetting(Serializable key, Object defaultValue);
/**
* Tells if this custom setting is set directly in this object (not in its parent
* {@link ProcessingConfiguration}). If not, then depending on the implementing class, reading the custom
* attribute might return the value of the setting from a parent object, or returns {@code null}, or throws a
* {@link CoreSettingValueNotSetException}. Note that if an attribute was set to {@code
* null} (as opposed to not set at all) then this method will return {@code true}.
*/
boolean isCustomSettingSet(Serializable key);
/**
* Collects all {@linkplain #getCustomSetting(Serializable)} custom settings} into a {@link Map} (which is a
* snapshot); mostly useful for debugging and tooling, and is possibly too slow to call very frequently.
*
* @param includeInherited
* If {@code false}, only the custom settings set in this {@link ProcessingConfiguration} will be
* collected, otherwise the custom settings inherited from the parent {@link ProcessingConfiguration}-s
* will be too. Note that it's the last that matches the behavior of {@link
* #getCustomSetting(Serializable)}.
*
* @return An unmodifiable and unchanging {@link Map}; not {@code null}. The object identity of keys and values of
* this {@link Map} will not change when custom settings are set/unset later (it's a snapshot). But, if
* a key or value objects are themselves mutable objects, FreeMarker can't prevent their content from changing.
* You shouldn't change the content of those objects.
*/
Map<Serializable, Object> getCustomSettings(boolean includeInherited);
/**
* The algorithm used for {@code ?truncate}. Defaults to {@link DefaultTruncateBuiltinAlgorithm#ASCII_INSTANCE}.
* Most customization needs can be addressed by creating a new {@link DefaultTruncateBuiltinAlgorithm} with the
* proper constructor parameters. Otherwise users my use their own {@link TruncateBuiltinAlgorithm} implementation.
*
* <p>In case you need to set this with {@link Properties}, or a similar configuration approach that doesn't let you
* create the value in Java, see examples at {@link MutableProcessingConfiguration#setSetting(String, String)}.
*/
public TruncateBuiltinAlgorithm getTruncateBuiltinAlgorithm();
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
* the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
* an {@link CoreSettingValueNotSetException}.
*/
public boolean isTruncateBuiltinAlgorithmSet();
}