Skip to content
This repository has been archived by the owner on Jan 8, 2020. It is now read-only.

Commit

Permalink
Replacing LocalTemplateDateFormatterFactory mechanism with a more gen…
Browse files Browse the repository at this point in the history
…eric env.customState feature.
  • Loading branch information
ddekany committed Aug 31, 2015
1 parent a26e832 commit 8d1e14f
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 420 deletions.
161 changes: 17 additions & 144 deletions src/main/java/freemarker/core/Environment.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ public final class Environment extends Configurable {
* (see {@link #getTemplateDateFormatCacheArrayIndex(int, boolean, boolean)}):<br>
* Zoned input: 0: U, 1: T, 2: D, 3: DT<br>
* Zoneless input: 4: U, 5: T, 6: D, 7: DT<br>
* Sys def TZ + Zoned input: 8: U, 9: T, 10: D, 11: DT<br>
* Sys def TZ + Zoneless input: 12: U, 13: T, 14: D, 15: DT
* SQL D T TZ + Zoned input: 8: U, 9: T, 10: D, 11: DT<br>
* SQL D T TZ + Zoneless input: 12: U, 13: T, 14: D, 15: DT
*
* <p>This is a lazily filled cache. It starts out as {@code null}, then
* when first needed the array will be created. The array elements also start out as {@code null}-s, and they
Expand All @@ -132,18 +132,8 @@ public final class Environment extends Configurable {
/** Similar to {@link #cachedTempDateFormatArray}, but used when a formatting string was specified. */
private HashMap<String, TemplateDateFormat>[] cachedTempDateFormatsByFmtStrArray;
private static final int CACHED_TDFS_ZONELESS_INPUT_OFFS = 4;
private static final int CACHED_TDFS_DEF_SYS_TZ_OFFS = CACHED_TDFS_ZONELESS_INPUT_OFFS * 2;
private static final int CACHED_TDFS_LENGTH = CACHED_TDFS_DEF_SYS_TZ_OFFS * 2;
private static final int CACHED_TDFS_SQL_D_T_TZ_OFFS = CACHED_TDFS_DEF_SYS_TZ_OFFS;

private XSLocalTemplateDateFormatFactory cachedXSLocTempDateFormatFactory;
private XSLocalTemplateDateFormatFactory cachedSQLDTXSLocTempDateFormatFactory;
private ISOLocalTemplateDateFormatFactory cachedISOLocTempDateFormatFactory;
private ISOLocalTemplateDateFormatFactory cachedSQLDTISOLocTempDateFormatFactory;
private JavaLocalTemplateDateFormatFactory cachedJavaLocTempDateFormatFactory;
private JavaLocalTemplateDateFormatFactory cachedSQLDTJavaLocTempDateFormatFactory;
private Map<String, LocalTemplateDateFormatFactory> cachedCustomLocTempDateFormatFactories;
private Map<String, LocalTemplateDateFormatFactory> cachedSQLDTCustomLocTempDateFormatFactories;
private static final int CACHED_TDFS_SQL_D_T_TZ_OFFS = CACHED_TDFS_ZONELESS_INPUT_OFFS * 2;
private static final int CACHED_TDFS_LENGTH = CACHED_TDFS_SQL_D_T_TZ_OFFS * 2;

/** Caches the result of {@link #isSQLDateAndTimeTimeZoneSameAsNormal()}. */
private Boolean cachedSQLDateAndTimeTimeZoneSameAsNormal;
Expand Down Expand Up @@ -285,10 +275,6 @@ private void clearCachedValues() {

cachedTempDateFormatArray = null;
cachedTempDateFormatsByFmtStrArray = null;
cachedXSLocTempDateFormatFactory = cachedSQLDTXSLocTempDateFormatFactory = null;
cachedISOLocTempDateFormatFactory = cachedSQLDTISOLocTempDateFormatFactory = null;
cachedJavaLocTempDateFormatFactory = cachedSQLDTJavaLocTempDateFormatFactory = null;
cachedCustomLocTempDateFormatFactories = cachedSQLDTCustomLocTempDateFormatFactories = null;

cachedCollator = null;
cachedURLEscapingCharset = null;
Expand Down Expand Up @@ -846,38 +832,6 @@ public void setLocale(Locale locale) {
}

cachedTempDateFormatsByFmtStrArray = null;

if (cachedXSLocTempDateFormatFactory != null) {
cachedXSLocTempDateFormatFactory.setLocale(locale);
}
if (cachedSQLDTXSLocTempDateFormatFactory != null) {
cachedSQLDTXSLocTempDateFormatFactory.setLocale(locale);;
}

if (cachedISOLocTempDateFormatFactory != null) {
cachedISOLocTempDateFormatFactory.setLocale(locale);
}
if (cachedSQLDTISOLocTempDateFormatFactory != null) {
cachedSQLDTISOLocTempDateFormatFactory.setLocale(locale);
}

if (cachedJavaLocTempDateFormatFactory != null) {
cachedJavaLocTempDateFormatFactory.setLocale(locale);
}
if (cachedSQLDTJavaLocTempDateFormatFactory != null) {
cachedSQLDTJavaLocTempDateFormatFactory.setLocale(locale);
}

if (cachedCustomLocTempDateFormatFactories != null) {
for (LocalTemplateDateFormatFactory fact : cachedCustomLocTempDateFormatFactories.values()) {
fact.setLocale(locale);
}
}
if (cachedSQLDTCustomLocTempDateFormatFactories != null) {
for (LocalTemplateDateFormatFactory fact : cachedSQLDTCustomLocTempDateFormatFactories.values()) {
fact.setLocale(locale);
}
}

cachedCollator = null;
}
Expand All @@ -900,21 +854,6 @@ public void setTimeZone(TimeZone timeZone) {
}
}

if (cachedXSLocTempDateFormatFactory != null) {
cachedXSLocTempDateFormatFactory.setTimeZone(timeZone);
}
if (cachedISOLocTempDateFormatFactory != null) {
cachedISOLocTempDateFormatFactory.setTimeZone(timeZone);
}
if (cachedJavaLocTempDateFormatFactory != null) {
cachedJavaLocTempDateFormatFactory.setTimeZone(timeZone);
}
if (cachedCustomLocTempDateFormatFactories != null) {
for (LocalTemplateDateFormatFactory locFact : cachedCustomLocTempDateFormatFactories.values()) {
locFact.setTimeZone(timeZone);
}
}

cachedSQLDateAndTimeTimeZoneSameAsNormal = null;
}
}
Expand All @@ -939,21 +878,6 @@ public void setSQLDateAndTimeTimeZone(TimeZone timeZone) {
}
}

if (cachedSQLDTXSLocTempDateFormatFactory != null) {
cachedSQLDTXSLocTempDateFormatFactory.setTimeZone(timeZone);
}
if (cachedSQLDTISOLocTempDateFormatFactory != null) {
cachedSQLDTISOLocTempDateFormatFactory.setTimeZone(timeZone);
}
if (cachedSQLDTJavaLocTempDateFormatFactory != null) {
cachedSQLDTJavaLocTempDateFormatFactory.setTimeZone(timeZone);
}
if (cachedSQLDTCustomLocTempDateFormatFactories != null) {
for (LocalTemplateDateFormatFactory locFact : cachedSQLDTCustomLocTempDateFormatFactories.values()) {
locFact.setTimeZone(timeZone);
}
}

cachedSQLDateAndTimeTimeZoneSameAsNormal = null;
}
}
Expand Down Expand Up @@ -1417,12 +1341,12 @@ TemplateDateFormat getTemplateDateFormat(

/**
* @param dateType
* See the similar parameter of {@link LocalTemplateDateFormatFactory#get(int, boolean, String)}
* See the similar parameter of {@link TemplateDateFormatFactory#get}
* @param zonelessInput
* See the similar parameter of {@link LocalTemplateDateFormatFactory#get(int, boolean, String)}
* See the similar parameter of {@link TemplateDateFormatFactory#get}
* @param formatString
* The string that describes the date format. See the similar parameter of
* {@link LocalTemplateDateFormatFactory#get(int, boolean, String)}
* {@link TemplateDateFormatFactory#get}
* @param formatStringCfgSettingName
* The name of the configuration setting where the {@code formatZtring} comes from, or {@code null}
* if the format string was specified directly for this formatting call.
Expand Down Expand Up @@ -1472,43 +1396,21 @@ private TemplateDateFormat getTemplateDateFormat(
final String formatParams;

// As of Java 8, 'x' and 'i' (in lower case) are illegal date format letters, so this is backward-compatible.
LocalTemplateDateFormatFactory locTempDateFormatFactory;
TemplateDateFormatFactory formatFactory;
char firstChar = formatStringLen != 0 ? formatString.charAt(0) : 0;
try {
if (
firstChar == 'x'
&& formatStringLen > 1
&& formatString.charAt(1) == 's') {
locTempDateFormatFactory = useSQLDTTZ
? cachedSQLDTXSLocTempDateFormatFactory : cachedXSLocTempDateFormatFactory;
if (locTempDateFormatFactory == null) {
locTempDateFormatFactory = new XSLocalTemplateDateFormatFactory(
this, useSQLDTTZ ? getSQLDateAndTimeTimeZone() : getTimeZone());
if (useSQLDTTZ) {
cachedSQLDTXSLocTempDateFormatFactory
= (XSLocalTemplateDateFormatFactory) locTempDateFormatFactory;
} else {
cachedXSLocTempDateFormatFactory = (XSLocalTemplateDateFormatFactory) locTempDateFormatFactory;
}
}
formatFactory = XSTemplateDateFormatFactory.INSTANCE;
formatParams = formatString; // for speed, we don't remove the prefix
} else if (
firstChar == 'i'
&& formatStringLen > 2
&& formatString.charAt(1) == 's'
&& formatString.charAt(2) == 'o') {
locTempDateFormatFactory = useSQLDTTZ
? cachedSQLDTISOLocTempDateFormatFactory : cachedISOLocTempDateFormatFactory;
if (locTempDateFormatFactory == null) {
locTempDateFormatFactory = new ISOLocalTemplateDateFormatFactory(
this, useSQLDTTZ ? getSQLDateAndTimeTimeZone() : getTimeZone());
if (useSQLDTTZ) {
cachedSQLDTISOLocTempDateFormatFactory
= (ISOLocalTemplateDateFormatFactory) locTempDateFormatFactory;
} else {
cachedISOLocTempDateFormatFactory = (ISOLocalTemplateDateFormatFactory) locTempDateFormatFactory;
}
}
formatFactory = ISOTemplateDateFormatFactory.INSTANCE;
formatParams = formatString; // for speed, we don't remove the prefix
} else if (firstChar == '@') {
final String name;
Expand All @@ -1524,47 +1426,18 @@ private TemplateDateFormat getTemplateDateFormat(
formatParams = endIdx < formatStringLen ? formatString.substring(endIdx + 1) : "";
}

Map<String, LocalTemplateDateFormatFactory> cachedLocalFormatFactories = useSQLDTTZ
? cachedSQLDTCustomLocTempDateFormatFactories
: cachedCustomLocTempDateFormatFactories;
locTempDateFormatFactory =
cachedLocalFormatFactories != null ? cachedLocalFormatFactories.get(name) : null;
if (locTempDateFormatFactory == null) {
TemplateDateFormatFactory formatFactory = getCustomDateFormat(name);
if (formatFactory == null) {
throw new UndefinedCustomFormatException(
"No custom date format was defined with name " + StringUtil.jQuote(name));
}
locTempDateFormatFactory = formatFactory.createLocalFactory(this,
getLocale(), useSQLDTTZ ? getSQLDateAndTimeTimeZone() : getTimeZone());
if (cachedLocalFormatFactories == null) {
cachedLocalFormatFactories = new HashMap();
}
if (useSQLDTTZ) {
cachedSQLDTCustomLocTempDateFormatFactories = cachedLocalFormatFactories;
} else {
cachedCustomLocTempDateFormatFactories = cachedLocalFormatFactories;
}
cachedLocalFormatFactories.put(name, locTempDateFormatFactory);
formatFactory = getCustomDateFormat(name);
if (formatFactory == null) {
throw new UndefinedCustomFormatException(
"No custom date format was defined with name " + StringUtil.jQuote(name));
}
} else {
locTempDateFormatFactory = useSQLDTTZ
? cachedSQLDTJavaLocTempDateFormatFactory : cachedJavaLocTempDateFormatFactory;
if (locTempDateFormatFactory == null) {
locTempDateFormatFactory = new JavaLocalTemplateDateFormatFactory(
this, getLocale(), useSQLDTTZ ? getSQLDateAndTimeTimeZone() : getTimeZone());
if (useSQLDTTZ) {
cachedSQLDTJavaLocTempDateFormatFactory
= (JavaLocalTemplateDateFormatFactory) locTempDateFormatFactory;
} else {
cachedJavaLocTempDateFormatFactory
= (JavaLocalTemplateDateFormatFactory) locTempDateFormatFactory;
}
}
formatFactory = JavaTemplateDateFormatFactory.INSTANCE;
formatParams = formatString;
}

TemplateDateFormat format = locTempDateFormatFactory.get(dateType, zonelessInput, formatParams);
TemplateDateFormat format = formatFactory.get(dateType, zonelessInput, formatParams, getLocale(),
useSQLDTTZ ? getSQLDateAndTimeTimeZone() : getTimeZone(), this);
if (cacheResult) {
// We know here that cachedFormatsByFormatString != null
cachedFormatsByFormatString.put(formatString, format);
Expand Down
10 changes: 6 additions & 4 deletions src/main/java/freemarker/core/ISOLikeTemplateDateFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ abstract class ISOLikeTemplateDateFormat extends TemplateDateFormat {

private static final String XS_LESS_THAN_SECONDS_ACCURACY_ERROR_MESSAGE
= "Less than seconds accuracy isn't allowed by the XML Schema format";
private final ISOLikeLocalTemplateDateFormatFactory factory;
private final ISOLikeTemplateDateFormatFactory factory;
private final Environment env;
protected final int dateType;
protected final boolean zonelessInput;
protected final TimeZone timeZone;
Expand All @@ -48,9 +49,10 @@ public ISOLikeTemplateDateFormat(
final String formatString, int parsingStart,
int dateType, boolean zonelessInput,
TimeZone timeZone,
ISOLikeLocalTemplateDateFormatFactory factory)
ISOLikeTemplateDateFormatFactory factory, Environment env)
throws InvalidFormatParametersException, UnknownDateTypeFormattingUnsupportedException {
this.factory = factory;
this.env = env;
if (dateType == TemplateDateModel.UNKNOWN) {
throw new UnknownDateTypeFormattingUnsupportedException();
}
Expand Down Expand Up @@ -182,7 +184,7 @@ public final String format(TemplateDateModel dateModel) throws TemplateModelExce
: showZoneOffset.booleanValue(),
accuracy,
(forceUTC == null ? !zonelessInput : forceUTC.booleanValue()) ? DateUtil.UTC : timeZone,
factory.getISOBuiltInCalendar());
factory.getISOBuiltInCalendar(env));
}

protected abstract String format(Date date,
Expand All @@ -193,7 +195,7 @@ protected abstract String format(Date date,

@Override
public final Date parse(String s) throws java.text.ParseException {
CalendarFieldsToDateConverter calToDateConverter = factory.getCalendarFieldsToDateCalculator();
CalendarFieldsToDateConverter calToDateConverter = factory.getCalendarFieldsToDateCalculator(env);
TimeZone tz = forceUTC != Boolean.FALSE ? DateUtil.UTC : timeZone;
if (dateType == TemplateDateModel.DATE) {
return parseDate(s, tz, calToDateConverter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,48 +16,34 @@

package freemarker.core;

import java.util.TimeZone;

import freemarker.template.utility.DateUtil.CalendarFieldsToDateConverter;
import freemarker.template.utility.DateUtil.DateToISO8601CalendarFactory;
import freemarker.template.utility.DateUtil.TrivialCalendarFieldsToDateConverter;
import freemarker.template.utility.DateUtil.TrivialDateToISO8601CalendarFactory;

abstract class ISOLikeLocalTemplateDateFormatFactory extends LocalTemplateDateFormatFactory {
abstract class ISOLikeTemplateDateFormatFactory extends TemplateDateFormatFactory {

private DateToISO8601CalendarFactory dateToCalenderFieldsCalculator;
private CalendarFieldsToDateConverter calendarFieldsToDateConverter;

public ISOLikeLocalTemplateDateFormatFactory(Environment env, TimeZone timeZone) {
super(env, null, timeZone);
}
private static final Object DATE_TO_CAL_CONVERTER_KEY = new Object();
private static final Object CAL_TO_DATE_CONVERTER_KEY = new Object();

protected ISOLikeTemplateDateFormatFactory() { }

public DateToISO8601CalendarFactory getISOBuiltInCalendar() {
DateToISO8601CalendarFactory r = dateToCalenderFieldsCalculator;
public DateToISO8601CalendarFactory getISOBuiltInCalendar(Environment env) {
DateToISO8601CalendarFactory r = (DateToISO8601CalendarFactory) env.getCustomState(DATE_TO_CAL_CONVERTER_KEY);
if (r == null) {
r = new TrivialDateToISO8601CalendarFactory();
dateToCalenderFieldsCalculator = r;
env.setCustomState(DATE_TO_CAL_CONVERTER_KEY, r);
}
return r;
}

public CalendarFieldsToDateConverter getCalendarFieldsToDateCalculator() {
CalendarFieldsToDateConverter r = calendarFieldsToDateConverter;
public CalendarFieldsToDateConverter getCalendarFieldsToDateCalculator(Environment env) {
CalendarFieldsToDateConverter r = (CalendarFieldsToDateConverter) env.getCustomState(CAL_TO_DATE_CONVERTER_KEY);
if (r == null) {
r = new TrivialCalendarFieldsToDateConverter();
calendarFieldsToDateConverter = r;
env.setCustomState(CAL_TO_DATE_CONVERTER_KEY, r);
}
return r;
}

@Override
protected void onLocaleChanged() {
// No op
}

@Override
protected void onTimeZoneChanged() {
// No op
}

}
5 changes: 3 additions & 2 deletions src/main/java/freemarker/core/ISOTemplateDateFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ final class ISOTemplateDateFormat extends ISOLikeTemplateDateFormat {
String settingValue, int parsingStart,
int dateType, boolean zonelessInput,
TimeZone timeZone,
ISOLikeLocalTemplateDateFormatFactory factory)
ISOLikeTemplateDateFormatFactory factory,
Environment env)
throws InvalidFormatParametersException, UnknownDateTypeFormattingUnsupportedException {
super(settingValue, parsingStart, dateType, zonelessInput, timeZone, factory);
super(settingValue, parsingStart, dateType, zonelessInput, timeZone, factory, env);
}

@Override
Expand Down
Loading

0 comments on commit 8d1e14f

Please sign in to comment.