http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/JavaTemplateNumberFormatFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/JavaTemplateNumberFormatFactory.java b/src/main/java/org/apache/freemarker/core/JavaTemplateNumberFormatFactory.java deleted file mode 100644 index e73e2ec..0000000 --- a/src/main/java/org/apache/freemarker/core/JavaTemplateNumberFormatFactory.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.freemarker.core; - -import java.text.NumberFormat; -import java.text.ParseException; -import java.util.Locale; -import java.util.concurrent.ConcurrentHashMap; - -import org.slf4j.Logger; - -/** - * Deals with {@link TemplateNumberFormat}-s that just wrap a Java {@link NumberFormat}. - */ -class JavaTemplateNumberFormatFactory extends TemplateNumberFormatFactory { - - static final JavaTemplateNumberFormatFactory INSTANCE = new JavaTemplateNumberFormatFactory(); - - private static final Logger LOG = _CoreLogs.RUNTIME; - - private static final ConcurrentHashMap<CacheKey, NumberFormat> GLOBAL_FORMAT_CACHE - = new ConcurrentHashMap<>(); - private static final int LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE = 1024; - - private JavaTemplateNumberFormatFactory() { - // Not meant to be instantiated - } - - @Override - public TemplateNumberFormat get(String params, Locale locale, Environment env) - throws InvalidFormatParametersException { - CacheKey cacheKey = new CacheKey(params, locale); - NumberFormat jFormat = GLOBAL_FORMAT_CACHE.get(cacheKey); - if (jFormat == null) { - if ("number".equals(params)) { - jFormat = NumberFormat.getNumberInstance(locale); - } else if ("currency".equals(params)) { - jFormat = NumberFormat.getCurrencyInstance(locale); - } else if ("percent".equals(params)) { - jFormat = NumberFormat.getPercentInstance(locale); - } else if ("computer".equals(params)) { - jFormat = env.getCNumberFormat(); - } else { - try { - jFormat = ExtendedDecimalFormatParser.parse(params, locale); - } catch (ParseException e) { - String msg = e.getMessage(); - throw new InvalidFormatParametersException( - msg != null ? msg : "Invalid DecimalFormat pattern", e); - } - } - - if (GLOBAL_FORMAT_CACHE.size() >= LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE) { - boolean triggered = false; - synchronized (JavaTemplateNumberFormatFactory.class) { - if (GLOBAL_FORMAT_CACHE.size() >= LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE) { - triggered = true; - GLOBAL_FORMAT_CACHE.clear(); - } - } - if (triggered) { - LOG.warn("Global Java NumberFormat cache has exceeded {} entries => cache flushed. " - + "Typical cause: Some template generates high variety of format pattern strings.", - LEAK_ALERT_NUMBER_FORMAT_CACHE_SIZE); - } - } - - NumberFormat prevJFormat = GLOBAL_FORMAT_CACHE.putIfAbsent(cacheKey, jFormat); - if (prevJFormat != null) { - jFormat = prevJFormat; - } - } // if cache miss - - // JFormat-s aren't thread-safe; must clone it - jFormat = (NumberFormat) jFormat.clone(); - - return new JavaTemplateNumberFormat(jFormat, params); - } - - private static final class CacheKey { - private final String pattern; - private final Locale locale; - - CacheKey(String pattern, Locale locale) { - this.pattern = pattern; - this.locale = locale; - } - - @Override - public boolean equals(Object o) { - if (o instanceof CacheKey) { - CacheKey fk = (CacheKey) o; - return fk.pattern.equals(pattern) && fk.locale.equals(locale); - } - return false; - } - - @Override - public int hashCode() { - return pattern.hashCode() ^ locale.hashCode(); - } - } - -}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/MessageUtil.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/MessageUtil.java b/src/main/java/org/apache/freemarker/core/MessageUtil.java index c0f6a96..4e658db 100644 --- a/src/main/java/org/apache/freemarker/core/MessageUtil.java +++ b/src/main/java/org/apache/freemarker/core/MessageUtil.java @@ -24,6 +24,10 @@ import java.util.ArrayList; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelException; import org.apache.freemarker.core.util._StringUtil; +import org.apache.freemarker.core.valueformat.TemplateDateFormat; +import org.apache.freemarker.core.valueformat.TemplateNumberFormat; +import org.apache.freemarker.core.valueformat.TemplateValueFormatException; +import org.apache.freemarker.core.valueformat.UnknownDateTypeFormattingUnsupportedException; /** * Utilities for creating error messages (and other messages). @@ -34,13 +38,9 @@ class MessageUtil { = "Can't convert the date-like value to string because it isn't " + "known if it's a date (no time part), time or date-time value."; - static final String UNKNOWN_DATE_PARSING_ERROR_MESSAGE - = "Can't parse the string to date-like value because it isn't " - + "known if it's desired result should be a date (no time part), a time, or a date-time value."; - - static final String UNKNOWN_DATE_TYPE_ERROR_TIP = + static final String UNKNOWN_DATE_TYPE_ERROR_TIP = "Use ?date, ?time, or ?datetime to tell FreeMarker the exact type."; - + static final Object[] UNKNOWN_DATE_TO_STRING_TIPS = { UNKNOWN_DATE_TYPE_ERROR_TIP, "If you need a particular format only once, use ?string(pattern), like ?string('dd.MM.yyyy HH:mm:ss'), " @@ -53,7 +53,7 @@ class MessageUtil { // Can't be instantiated private MessageUtil() { } - + static String formatLocationForSimpleParsingError(Template template, int line, int column) { return formatLocation("in", template, line, column); } @@ -78,7 +78,7 @@ class MessageUtil { Template t = macro.getTemplate(); return formatLocation("at", t != null ? t.getSourceName() : null, macro.getName(), macro.isFunction(), line, column); } - + static String formatLocationForEvaluationError(String templateSourceName, int line, int column) { return formatLocation("at", templateSourceName, line, column); } @@ -86,7 +86,7 @@ class MessageUtil { private static String formatLocation(String preposition, Template template, int line, int column) { return formatLocation(preposition, template != null ? template.getSourceName() : null, line, column); } - + private static String formatLocation(String preposition, String templateSourceName, int line, int column) { return formatLocation( preposition, templateSourceName, @@ -102,7 +102,7 @@ class MessageUtil { if (line < 0) { templateDesc = "?eval-ed string"; macroOrFuncName = null; - } else { + } else { templateDesc = templateSourceName != null ? "template " + _StringUtil.jQuoteNoXSS(templateSourceName) : "nameless template"; @@ -114,7 +114,7 @@ class MessageUtil { + " " + preposition + " " + formatPosition(line, column); } - + static String formatPosition(int line, int column) { return "line " + (line >= 0 ? line : line - (ASTNode.RUNTIME_EVAL_LINE_DISPLACEMENT - 1)) + ", column " + column; @@ -123,11 +123,11 @@ class MessageUtil { /** * Returns a single line string that is no longer than {@code maxLength}. * If will truncate the string at line-breaks too. - * The truncation is always signaled with a a {@code "..."} at the end of the result string. + * The truncation is always signaled with a a {@code "..."} at the end of the result string. */ static String shorten(String s, int maxLength) { if (maxLength < 5) maxLength = 5; - + boolean isTruncated = false; int brIdx = s.indexOf('\n'); @@ -286,7 +286,7 @@ class MessageUtil { "Instantiating ", className, " is not allowed in the template for security reasons."); } - static _TemplateModelException newCantFormatUnknownTypeDateException( + static TemplateModelException newCantFormatUnknownTypeDateException( ASTExpression dateSourceExpr, UnknownDateTypeFormattingUnsupportedException cause) { return new _TemplateModelException(cause, null, new _ErrorDescriptionBuilder( MessageUtil.UNKNOWN_DATE_TO_STRING_ERROR_MESSAGE) @@ -295,7 +295,7 @@ class MessageUtil { } static TemplateException newCantFormatDateException(TemplateDateFormat format, ASTExpression dataSrcExp, - TemplateValueFormatException e, boolean useTempModelExc) { + TemplateValueFormatException e, boolean useTempModelExc) { _ErrorDescriptionBuilder desc = new _ErrorDescriptionBuilder( "Failed to format date/time/datetime with format ", new _DelayedJQuote(format.getDescription()), ": ", e.getMessage()) @@ -306,7 +306,7 @@ class MessageUtil { } static TemplateException newCantFormatNumberException(TemplateNumberFormat format, ASTExpression dataSrcExp, - TemplateValueFormatException e, boolean useTempModelExc) { + TemplateValueFormatException e, boolean useTempModelExc) { _ErrorDescriptionBuilder desc = new _ErrorDescriptionBuilder( "Failed to format number with format ", new _DelayedJQuote(format.getDescription()), ": ", e.getMessage()) http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/ParsingNotSupportedException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ParsingNotSupportedException.java b/src/main/java/org/apache/freemarker/core/ParsingNotSupportedException.java deleted file mode 100644 index bac087a..0000000 --- a/src/main/java/org/apache/freemarker/core/ParsingNotSupportedException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.freemarker.core; - -/** - * Thrown when the {@link TemplateValueFormat} doesn't support parsing, and parsing was invoked. - * - * @since 2.3.24 - */ -public class ParsingNotSupportedException extends TemplateValueFormatException { - - public ParsingNotSupportedException(String message, Throwable cause) { - super(message, cause); - } - - public ParsingNotSupportedException(String message) { - this(message, null); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java b/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java index 0a01c14..aaea96e 100644 --- a/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java +++ b/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java @@ -30,6 +30,8 @@ import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.outputformat.OutputFormat; import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateResolver; import org.apache.freemarker.core.util._NullArgumentException; +import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory; +import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; /** * Used for customizing the configuration settings for individual {@link Template}-s (or rather groups of templates), http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/TemplateDateFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/TemplateDateFormat.java b/src/main/java/org/apache/freemarker/core/TemplateDateFormat.java deleted file mode 100644 index ed7f996..0000000 --- a/src/main/java/org/apache/freemarker/core/TemplateDateFormat.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.freemarker.core; - -import java.text.DateFormat; -import java.util.Date; - -import org.apache.freemarker.core.model.TemplateDateModel; -import org.apache.freemarker.core.model.TemplateMarkupOutputModel; -import org.apache.freemarker.core.model.TemplateModelException; - -/** - * Represents a date/time/dateTime format; used in templates for formatting and parsing with that format. This is - * similar to Java's {@link DateFormat}, but made to fit the requirements of FreeMarker. Also, it makes easier to define - * formats that can't be represented with Java's existing {@link DateFormat} implementations. - * - * <p> - * Implementations need not be thread-safe if the {@link TemplateNumberFormatFactory} doesn't recycle them among - * different {@link Environment}-s. As far as FreeMarker's concerned, instances are bound to a single - * {@link Environment}, and {@link Environment}-s are thread-local objects. - * - * @since 2.3.24 - */ -public abstract class TemplateDateFormat extends TemplateValueFormat { - - /** - * @param dateModel - * The date/time/dateTime to format; not {@code null}. Most implementations will just work with the return value of - * {@link TemplateDateModel#getAsDate()}, but some may format differently depending on the properties of - * a custom {@link TemplateDateModel} implementation. - * - * @return The date/time/dateTime as text, with no escaping (like no HTML escaping); can't be {@code null}. - * - * @throws TemplateValueFormatException - * When a problem occurs during the formatting of the value. Notable subclass: - * {@link UnknownDateTypeFormattingUnsupportedException} - * @throws TemplateModelException - * Exception thrown by the {@code dateModel} object when calling its methods. - */ - public abstract String formatToPlainText(TemplateDateModel dateModel) - throws TemplateValueFormatException, TemplateModelException; - - /** - * Formats the model to markup instead of to plain text if the result markup will be more than just plain text - * escaped, otherwise falls back to formatting to plain text. If the markup result would be just the result of - * {@link #formatToPlainText(TemplateDateModel)} escaped, it must return the {@link String} that - * {@link #formatToPlainText(TemplateDateModel)} does. - * - * <p>The implementation in {@link TemplateDateFormat} simply calls {@link #formatToPlainText(TemplateDateModel)}. - * - * @return A {@link String} or a {@link TemplateMarkupOutputModel}; not {@code null}. - */ - public Object format(TemplateDateModel dateModel) throws TemplateValueFormatException, TemplateModelException { - return formatToPlainText(dateModel); - } - - /** - * Parsers a string to date/time/datetime, according to this format. Some format implementations may throw - * {@link ParsingNotSupportedException} here. - * - * @param s - * The string to parse - * @param dateType - * The expected date type of the result. Not all {@link TemplateDateFormat}-s will care about this; - * though those who return a {@link TemplateDateModel} instead of {@link Date} often will. When strings - * are parsed via {@code ?date}, {@code ?time}, or {@code ?datetime}, then this parameter is - * {@link TemplateDateModel#DATE}, {@link TemplateDateModel#TIME}, or {@link TemplateDateModel#DATETIME}, - * respectively. This parameter rarely if ever {@link TemplateDateModel#UNKNOWN}, but the implementation - * that cares about this parameter should be prepared for that. If nothing else, it should throw - * {@link UnknownDateTypeParsingUnsupportedException} then. - * - * @return The interpretation of the text either as a {@link Date} or {@link TemplateDateModel}. Typically, a - * {@link Date}. {@link TemplateDateModel} is used if you have to attach some application-specific - * meta-information thats also extracted during {@link #formatToPlainText(TemplateDateModel)} (so if you format - * something and then parse it, you get back an equivalent result). It can't be {@code null}. Known issue - * (at least in FTL 2): {@code ?date}/{@code ?time}/{@code ?datetime}, when not invoked as a method, can't - * return the {@link TemplateDateModel}, only the {@link Date} from inside it, hence the additional - * application-specific meta-info will be lost. - */ - public abstract Object parse(String s, int dateType) throws TemplateValueFormatException; - - /** - * Tells if this formatter should be re-created if the locale changes. - */ - public abstract boolean isLocaleBound(); - - /** - * Tells if this formatter should be re-created if the time zone changes. Currently always {@code true}. - */ - public abstract boolean isTimeZoneBound(); - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/TemplateDateFormatFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/TemplateDateFormatFactory.java b/src/main/java/org/apache/freemarker/core/TemplateDateFormatFactory.java deleted file mode 100644 index 6a6fb14..0000000 --- a/src/main/java/org/apache/freemarker/core/TemplateDateFormatFactory.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.freemarker.core; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; - -import org.apache.freemarker.core.model.TemplateDateModel; - -/** - * Factory for a certain kind of date/time/dateTime formatting ({@link TemplateDateFormat}). Usually a singleton - * (one-per-VM or one-per-{@link Configuration}), and so must be thread-safe. - * - * @see Configurable#setCustomDateFormats(java.util.Map) - * - * @since 2.3.24 - */ -public abstract class TemplateDateFormatFactory extends TemplateValueFormatFactory { - - /** - * Returns a formatter for the given parameters. - * - * <p> - * The returned formatter can be a new instance or a reused (cached) instance. Note that {@link Environment} itself - * caches the returned instances, though that cache is lost with the {@link Environment} (i.e., when the top-level - * template execution ends), also it might flushes lot of entries if the locale or time zone is changed during - * template execution. So caching on the factory level is still useful, unless creating the formatters is - * sufficiently cheap. - * - * @param params - * The string that further describes how the format should look. For example, when the - * {@link Configurable#getDateFormat() dateFormat} is {@code "@fooBar 1, 2"}, then it will be - * {@code "1, 2"} (and {@code "@fooBar"} selects the factory). The format of this string is up to the - * {@link TemplateDateFormatFactory} implementation. Not {@code null}, often an empty string. - * @param dateType - * {@link TemplateDateModel#DATE}, {@link TemplateDateModel#TIME}, {@link TemplateDateModel#DATETIME} or - * {@link TemplateDateModel#UNKNOWN}. Supporting {@link TemplateDateModel#UNKNOWN} is not necessary, in - * which case the method should throw an {@link UnknownDateTypeFormattingUnsupportedException} exception. - * @param locale - * The locale to format for. Not {@code null}. The resulting format should be bound to this locale - * forever (i.e. locale changes in the {@link Environment} must not be followed). - * @param timeZone - * The time zone to format for. Not {@code null}. The resulting format must be bound to this time zone - * forever (i.e. time zone changes in the {@link Environment} must not be followed). - * @param zonelessInput - * Indicates that the input Java {@link Date} is not from a time zone aware source. When this is - * {@code true}, the formatters shouldn't override the time zone provided to its constructor (most - * formatters don't do that anyway), and it shouldn't show the time zone, if it can hide it (like a - * {@link SimpleDateFormat} pattern-based formatter may can't do that, as the pattern prescribes what to - * show). - * <p> - * As of FreeMarker 2.3.21, this is {@code true} exactly when the date is an SQL "date without time of - * the day" (i.e., a {@link java.sql.Date java.sql.Date}) or an SQL "time of the day" value (i.e., a - * {@link java.sql.Time java.sql.Time}, although this rule can change in future, depending on - * configuration settings and such, so you shouldn't rely on this rule, just accept what this parameter - * says. - * @param env - * The runtime environment from which the formatting was called. This is mostly meant to be used for - * {@link Environment#setCustomState(Object, Object)}/{@link Environment#getCustomState(Object)}. - * - * @throws TemplateValueFormatException - * If any problem occurs while parsing/getting the format. Notable subclasses: - * {@link InvalidFormatParametersException} if {@code params} is malformed; - * {@link UnknownDateTypeFormattingUnsupportedException} if {@code dateType} is - * {@link TemplateDateModel#UNKNOWN} and that's unsupported by this factory. - */ - public abstract TemplateDateFormat get( - String params, - int dateType, Locale locale, TimeZone timeZone, boolean zonelessInput, - Environment env) - throws TemplateValueFormatException; - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/TemplateFormatUtil.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/TemplateFormatUtil.java b/src/main/java/org/apache/freemarker/core/TemplateFormatUtil.java deleted file mode 100644 index c43d7f2..0000000 --- a/src/main/java/org/apache/freemarker/core/TemplateFormatUtil.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.freemarker.core; - -import java.util.Date; - -import org.apache.freemarker.core.model.ObjectWrapper; -import org.apache.freemarker.core.model.TemplateDateModel; -import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.TemplateNumberModel; - -/** - * Utility classes for implementing {@link TemplateValueFormat}-s. - * - * @since 2.3.24 - */ -public final class TemplateFormatUtil { - - private TemplateFormatUtil() { - // Not meant to be instantiated - } - - public static void checkHasNoParameters(String params) throws InvalidFormatParametersException - { - if (params.length() != 0) { - throw new InvalidFormatParametersException( - "This number format doesn't support any parameters."); - } - } - - /** - * Utility method to extract the {@link Number} from an {@link TemplateNumberModel}, and throws - * {@link TemplateModelException} with a standard error message if that's {@code null}. {@link TemplateNumberModel} - * that store {@code null} are in principle not allowed, and so are considered to be bugs in the - * {@link ObjectWrapper} or {@link TemplateNumberModel} implementation. - */ - public static Number getNonNullNumber(TemplateNumberModel numberModel) - throws TemplateModelException, UnformattableValueException { - Number number = numberModel.getAsNumber(); - if (number == null) { - throw EvalUtil.newModelHasStoredNullException(Number.class, numberModel, null); - } - return number; - } - - /** - * Utility method to extract the {@link Date} from an {@link TemplateDateModel}, and throw - * {@link TemplateModelException} with a standard error message if that's {@code null}. {@link TemplateDateModel} - * that store {@code null} are in principle not allowed, and so are considered to be bugs in the - * {@link ObjectWrapper} or {@link TemplateNumberModel} implementation. - */ - public static Date getNonNullDate(TemplateDateModel dateModel) throws TemplateModelException { - Date date = dateModel.getAsDate(); - if (date == null) { - throw EvalUtil.newModelHasStoredNullException(Date.class, dateModel, null); - } - return date; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/TemplateNumberFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/TemplateNumberFormat.java b/src/main/java/org/apache/freemarker/core/TemplateNumberFormat.java deleted file mode 100644 index cc35724..0000000 --- a/src/main/java/org/apache/freemarker/core/TemplateNumberFormat.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.freemarker.core; - -import java.text.NumberFormat; - -import org.apache.freemarker.core.model.TemplateDateModel; -import org.apache.freemarker.core.model.TemplateMarkupOutputModel; -import org.apache.freemarker.core.model.TemplateModelException; -import org.apache.freemarker.core.model.TemplateNumberModel; - -/** - * Represents a number format; used in templates for formatting and parsing with that format. This is similar to Java's - * {@link NumberFormat}, but made to fit the requirements of FreeMarker. Also, it makes easier to define formats that - * can't be represented with Java's existing {@link NumberFormat} implementations. - * - * <p> - * Implementations need not be thread-safe if the {@link TemplateNumberFormatFactory} doesn't recycle them among - * different {@link Environment}-s. As far as FreeMarker's concerned, instances are bound to a single - * {@link Environment}, and {@link Environment}-s are thread-local objects. - * - * @since 2.3.24 - */ -public abstract class TemplateNumberFormat extends TemplateValueFormat { - - /** - * @param numberModel - * The number to format; not {@code null}. Most implementations will just work with the return value of - * {@link TemplateDateModel#getAsDate()}, but some may format differently depending on the properties of - * a custom {@link TemplateDateModel} implementation. - * - * @return The number as text, with no escaping (like no HTML escaping); can't be {@code null}. - * - * @throws TemplateValueFormatException - * If any problem occurs while parsing/getting the format. Notable subclass: - * {@link UnformattableValueException}. - * @throws TemplateModelException - * Exception thrown by the {@code dateModel} object when calling its methods. - */ - public abstract String formatToPlainText(TemplateNumberModel numberModel) - throws TemplateValueFormatException, TemplateModelException; - - /** - * Formats the model to markup instead of to plain text if the result markup will be more than just plain text - * escaped, otherwise falls back to formatting to plain text. If the markup result would be just the result of - * {@link #formatToPlainText(TemplateNumberModel)} escaped, it must return the {@link String} that - * {@link #formatToPlainText(TemplateNumberModel)} does. - * - * <p> - * The implementation in {@link TemplateNumberFormat} simply calls {@link #formatToPlainText(TemplateNumberModel)}. - * - * @return A {@link String} or a {@link TemplateMarkupOutputModel}; not {@code null}. - */ - public Object format(TemplateNumberModel numberModel) - throws TemplateValueFormatException, TemplateModelException { - return formatToPlainText(numberModel); - } - - /** - * Tells if this formatter should be re-created if the locale changes. - */ - public abstract boolean isLocaleBound(); - - /** - * This method is reserved for future purposes; currently it always throws {@link ParsingNotSupportedException}. We - * don't yet support number parsing with {@link TemplateNumberFormat}-s, because currently FTL parses strings to - * number with the {@link ArithmeticEngine} ({@link TemplateNumberFormat} were only introduced in 2.3.24). If it - * will be support, it will be similar to {@link TemplateDateFormat#parse(String, int)}. - */ - public final Object parse(String s) throws TemplateValueFormatException { - throw new ParsingNotSupportedException("Number formats currenly don't support parsing"); - } - - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/TemplateNumberFormatFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/TemplateNumberFormatFactory.java b/src/main/java/org/apache/freemarker/core/TemplateNumberFormatFactory.java deleted file mode 100644 index 4decb91..0000000 --- a/src/main/java/org/apache/freemarker/core/TemplateNumberFormatFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.freemarker.core; - -import java.util.Locale; - -/** - * Factory for a certain kind of number formatting ({@link TemplateNumberFormat}). Usually a singleton (one-per-VM or - * one-per-{@link Configuration}), and so must be thread-safe. - * - * @see Configurable#setCustomNumberFormats(java.util.Map) - * - * @since 2.3.24 - */ -public abstract class TemplateNumberFormatFactory extends TemplateValueFormatFactory { - - /** - * Returns a formatter for the given parameters. - * - * <p> - * The returned formatter can be a new instance or a reused (cached) instance. Note that {@link Environment} itself - * caches the returned instances, though that cache is lost with the {@link Environment} (i.e., when the top-level - * template execution ends), also it might flushes lot of entries if the locale or time zone is changed during - * template execution. So caching on the factory level is still useful, unless creating the formatters is - * sufficiently cheap. - * - * @param params - * The string that further describes how the format should look. For example, when the - * {@link Configurable#getNumberFormat() numberFormat} is {@code "@fooBar 1, 2"}, then it will be - * {@code "1, 2"} (and {@code "@fooBar"} selects the factory). The format of this string is up to the - * {@link TemplateNumberFormatFactory} implementation. Not {@code null}, often an empty string. - * @param locale - * The locale to format for. Not {@code null}. The resulting format must be bound to this locale - * forever (i.e. locale changes in the {@link Environment} must not be followed). - * @param env - * The runtime environment from which the formatting was called. This is mostly meant to be used for - * {@link Environment#setCustomState(Object, Object)}/{@link Environment#getCustomState(Object)}. - * - * @throws TemplateValueFormatException - * if any problem occurs while parsing/getting the format. Notable subclasses: - * {@link InvalidFormatParametersException} if the {@code params} is malformed. - */ - public abstract TemplateNumberFormat get(String params, Locale locale, Environment env) - throws TemplateValueFormatException; - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/TemplateValueFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/TemplateValueFormat.java b/src/main/java/org/apache/freemarker/core/TemplateValueFormat.java deleted file mode 100644 index cc2833c..0000000 --- a/src/main/java/org/apache/freemarker/core/TemplateValueFormat.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.freemarker.core; - -/** - * Superclass of all value format objects; objects that convert values to strings, or parse strings. - * - * @since 2.3.24 - */ -public abstract class TemplateValueFormat { - - /** - * Meant to be used in error messages to tell what format the parsed string didn't fit. - */ - public abstract String getDescription(); - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/TemplateValueFormatException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/TemplateValueFormatException.java b/src/main/java/org/apache/freemarker/core/TemplateValueFormatException.java deleted file mode 100644 index f952369..0000000 --- a/src/main/java/org/apache/freemarker/core/TemplateValueFormatException.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.freemarker.core; - -/** - * Error while getting, creating or applying {@link TemplateValueFormat}-s (including its subclasses, like - * {@link TemplateNumberFormat}). - * - * @since 2.3.24 - */ -public abstract class TemplateValueFormatException extends Exception { - - public TemplateValueFormatException(String message, Throwable cause) { - super(message, cause); - } - - public TemplateValueFormatException(String message) { - super(message); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/TemplateValueFormatFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/TemplateValueFormatFactory.java b/src/main/java/org/apache/freemarker/core/TemplateValueFormatFactory.java deleted file mode 100644 index 3c504de..0000000 --- a/src/main/java/org/apache/freemarker/core/TemplateValueFormatFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.freemarker.core; - -/** - * Superclass of all format factories. - * - * @since 2.3.24 - */ -public abstract class TemplateValueFormatFactory { - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/UndefinedCustomFormatException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/UndefinedCustomFormatException.java b/src/main/java/org/apache/freemarker/core/UndefinedCustomFormatException.java deleted file mode 100644 index 26561f3..0000000 --- a/src/main/java/org/apache/freemarker/core/UndefinedCustomFormatException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.freemarker.core; - -/** - * @since 2.3.24 - */ -public class UndefinedCustomFormatException extends InvalidFormatStringException { - - public UndefinedCustomFormatException(String message, Throwable cause) { - super(message, cause); - } - - public UndefinedCustomFormatException(String message) { - super(message); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/UnformattableValueException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/UnformattableValueException.java b/src/main/java/org/apache/freemarker/core/UnformattableValueException.java deleted file mode 100644 index cb30c92..0000000 --- a/src/main/java/org/apache/freemarker/core/UnformattableValueException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.freemarker.core; - -import org.apache.freemarker.core.model.TemplateModel; - -/** - * Thrown when a {@link TemplateModel} can't be formatted because of the value/properties of it are outside of that the - * {@link TemplateValueFormat} supports. For example, a formatter may not support dates before year 1, or can't format - * NaN. The most often used subclass is {@link UnknownDateTypeFormattingUnsupportedException}. - * - * @since 2.3.24 - */ -public class UnformattableValueException extends TemplateValueFormatException { - - public UnformattableValueException(String message, Throwable cause) { - super(message, cause); - } - - public UnformattableValueException(String message) { - super(message); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/UnknownDateTypeFormattingUnsupportedException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/UnknownDateTypeFormattingUnsupportedException.java b/src/main/java/org/apache/freemarker/core/UnknownDateTypeFormattingUnsupportedException.java deleted file mode 100644 index aceca07..0000000 --- a/src/main/java/org/apache/freemarker/core/UnknownDateTypeFormattingUnsupportedException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.freemarker.core; - -import org.apache.freemarker.core.model.TemplateDateModel; - -/** - * Thrown when a {@link TemplateDateModel} can't be formatted because its type is {@link TemplateDateModel#UNKNOWN}. - * - * @since 2.3.24 - */ -public final class UnknownDateTypeFormattingUnsupportedException extends UnformattableValueException { - - public UnknownDateTypeFormattingUnsupportedException() { - super(MessageUtil.UNKNOWN_DATE_TO_STRING_ERROR_MESSAGE); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/UnknownDateTypeParsingUnsupportedException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/UnknownDateTypeParsingUnsupportedException.java b/src/main/java/org/apache/freemarker/core/UnknownDateTypeParsingUnsupportedException.java deleted file mode 100644 index a1173b6..0000000 --- a/src/main/java/org/apache/freemarker/core/UnknownDateTypeParsingUnsupportedException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.freemarker.core; - -import org.apache.freemarker.core.model.TemplateDateModel; - -/** - * Thrown when a string can't be parsed to {@link TemplateDateModel}, because the provided target type is - * {@link TemplateDateModel#UNKNOWN}. - * - * @since 2.3.24 - */ -public final class UnknownDateTypeParsingUnsupportedException extends UnformattableValueException { - - public UnknownDateTypeParsingUnsupportedException() { - super(MessageUtil.UNKNOWN_DATE_PARSING_ERROR_MESSAGE); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/UnparsableValueException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/UnparsableValueException.java b/src/main/java/org/apache/freemarker/core/UnparsableValueException.java deleted file mode 100644 index 37d979d..0000000 --- a/src/main/java/org/apache/freemarker/core/UnparsableValueException.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.freemarker.core; - -/** - * Thrown when the content of the string that should be parsed by the {@link TemplateValueFormat} doesn't match what the - * format expects. - * - * @since 2.3.24 - */ -public class UnparsableValueException extends TemplateValueFormatException { - - public UnparsableValueException(String message, Throwable cause) { - super(message, cause); - } - - public UnparsableValueException(String message) { - this(message, null); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/XSTemplateDateFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/XSTemplateDateFormat.java b/src/main/java/org/apache/freemarker/core/XSTemplateDateFormat.java deleted file mode 100644 index 56135f3..0000000 --- a/src/main/java/org/apache/freemarker/core/XSTemplateDateFormat.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.freemarker.core; - -import java.util.Date; -import java.util.TimeZone; - -import org.apache.freemarker.core.util._DateUtil; -import org.apache.freemarker.core.util._DateUtil.CalendarFieldsToDateConverter; -import org.apache.freemarker.core.util._DateUtil.DateParseException; -import org.apache.freemarker.core.util._DateUtil.DateToISO8601CalendarFactory; - -/** - * XML Schema format. - */ -final class XSTemplateDateFormat extends ISOLikeTemplateDateFormat { - - XSTemplateDateFormat( - String settingValue, int parsingStart, - int dateType, - boolean zonelessInput, - TimeZone timeZone, - ISOLikeTemplateDateFormatFactory factory, - Environment env) - throws UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException { - super(settingValue, parsingStart, dateType, zonelessInput, timeZone, factory, env); - } - - @Override - protected String format(Date date, boolean datePart, boolean timePart, boolean offsetPart, int accuracy, - TimeZone timeZone, DateToISO8601CalendarFactory calendarFactory) { - return _DateUtil.dateToXSString( - date, datePart, timePart, offsetPart, accuracy, timeZone, calendarFactory); - } - - @Override - protected Date parseDate(String s, TimeZone tz, CalendarFieldsToDateConverter calToDateConverter) - throws DateParseException { - return _DateUtil.parseXSDate(s, tz, calToDateConverter); - } - - @Override - protected Date parseTime(String s, TimeZone tz, CalendarFieldsToDateConverter calToDateConverter) - throws DateParseException { - return _DateUtil.parseXSTime(s, tz, calToDateConverter); - } - - @Override - protected Date parseDateTime(String s, TimeZone tz, - CalendarFieldsToDateConverter calToDateConverter) throws DateParseException { - return _DateUtil.parseXSDateTime(s, tz, calToDateConverter); - } - - @Override - protected String getDateDescription() { - return "W3C XML Schema date"; - } - - @Override - protected String getTimeDescription() { - return "W3C XML Schema time"; - } - - @Override - protected String getDateTimeDescription() { - return "W3C XML Schema dateTime"; - } - - @Override - protected boolean isXSMode() { - return true; - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/XSTemplateDateFormatFactory.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/XSTemplateDateFormatFactory.java b/src/main/java/org/apache/freemarker/core/XSTemplateDateFormatFactory.java deleted file mode 100644 index 9421cc0..0000000 --- a/src/main/java/org/apache/freemarker/core/XSTemplateDateFormatFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.freemarker.core; - -import java.util.Locale; -import java.util.TimeZone; - -class XSTemplateDateFormatFactory extends ISOLikeTemplateDateFormatFactory { - - static final XSTemplateDateFormatFactory INSTANCE = new XSTemplateDateFormatFactory(); - - private XSTemplateDateFormatFactory() { - // Not meant to be instantiated - } - - @Override - public TemplateDateFormat get(String params, int dateType, Locale locale, TimeZone timeZone, boolean zonelessInput, - Environment env) throws UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException { - // We don't cache these as creating them is cheap (only 10% speedup of ${d?string.xs} with caching) - return new XSTemplateDateFormat( - params, 2, - dateType, zonelessInput, - timeZone, this, env); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/_EvalUtil.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/_EvalUtil.java b/src/main/java/org/apache/freemarker/core/_EvalUtil.java new file mode 100644 index 0000000..fb0e7a5 --- /dev/null +++ b/src/main/java/org/apache/freemarker/core/_EvalUtil.java @@ -0,0 +1,543 @@ +/* + * 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 java.util.Date; + +import org.apache.freemarker.core.model.TemplateBooleanModel; +import org.apache.freemarker.core.model.TemplateCollectionModel; +import org.apache.freemarker.core.model.TemplateDateModel; +import org.apache.freemarker.core.model.TemplateMarkupOutputModel; +import org.apache.freemarker.core.model.TemplateModel; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.model.TemplateNumberModel; +import org.apache.freemarker.core.model.TemplateScalarModel; +import org.apache.freemarker.core.model.TemplateSequenceModel; +import org.apache.freemarker.core.outputformat.MarkupOutputFormat; +import org.apache.freemarker.core.util.BugException; +import org.apache.freemarker.core.valueformat.TemplateDateFormat; +import org.apache.freemarker.core.valueformat.TemplateNumberFormat; +import org.apache.freemarker.core.valueformat.TemplateValueFormat; +import org.apache.freemarker.core.valueformat.TemplateValueFormatException; + +/** + * Internally used static utilities for evaluation expressions. + */ +public class _EvalUtil { + static final int CMP_OP_EQUALS = 1; + static final int CMP_OP_NOT_EQUALS = 2; + static final int CMP_OP_LESS_THAN = 3; + static final int CMP_OP_GREATER_THAN = 4; + static final int CMP_OP_LESS_THAN_EQUALS = 5; + static final int CMP_OP_GREATER_THAN_EQUALS = 6; + // If you add a new operator here, update the "compare" and "cmpOpToString" methods! + + // Prevents instantination. + private _EvalUtil() { } + + /** + * @param expr {@code null} is allowed, but may results in less helpful error messages + * @param env {@code null} is allowed + */ + static String modelToString(TemplateScalarModel model, ASTExpression expr, Environment env) + throws TemplateModelException { + String value = model.getAsString(); + if (value == null) { + throw newModelHasStoredNullException(String.class, model, expr); + } + return value; + } + + /** + * @param expr {@code null} is allowed, but may results in less helpful error messages + */ + static Number modelToNumber(TemplateNumberModel model, ASTExpression expr) + throws TemplateModelException { + Number value = model.getAsNumber(); + if (value == null) throw newModelHasStoredNullException(Number.class, model, expr); + return value; + } + + /** + * @param expr {@code null} is allowed, but may results in less helpful error messages + */ + static Date modelToDate(TemplateDateModel model, ASTExpression expr) + throws TemplateModelException { + Date value = model.getAsDate(); + if (value == null) throw newModelHasStoredNullException(Date.class, model, expr); + return value; + } + + /** Signals the buggy case where we have a non-null model, but it wraps a null. */ + public static TemplateModelException newModelHasStoredNullException( + Class expected, TemplateModel model, ASTExpression expr) { + return new _TemplateModelException(expr, + _TemplateModelException.modelHasStoredNullDescription(expected, model)); + } + + /** + * Compares two expressions according the rules of the FTL comparator operators. + * + * @param leftExp not {@code null} + * @param operator one of the {@code COMP_OP_...} constants, like {@link #CMP_OP_EQUALS}. + * @param operatorString can be null {@code null}; the actual operator used, used for more accurate error message. + * @param rightExp not {@code null} + * @param env {@code null} is tolerated, but should be avoided + */ + static boolean compare( + ASTExpression leftExp, + int operator, String operatorString, + ASTExpression rightExp, + ASTExpression defaultBlamed, + Environment env) throws TemplateException { + TemplateModel ltm = leftExp.eval(env); + TemplateModel rtm = rightExp.eval(env); + return compare( + ltm, leftExp, + operator, operatorString, + rtm, rightExp, + defaultBlamed, false, + false, false, false, + env); + } + + /** + * Compares values according the rules of the FTL comparator operators; if the {@link ASTExpression}-s are + * accessible, use {@link #compare(ASTExpression, int, String, ASTExpression, ASTExpression, Environment)} instead, + * as that gives better error messages. + * + * @param leftValue maybe {@code null}, which will usually cause the appropriate {@link TemplateException}. + * @param operator one of the {@code COMP_OP_...} constants, like {@link #CMP_OP_EQUALS}. + * @param rightValue maybe {@code null}, which will usually cause the appropriate {@link TemplateException}. + * @param env {@code null} is tolerated, but should be avoided + */ + static boolean compare( + TemplateModel leftValue, int operator, TemplateModel rightValue, + Environment env) throws TemplateException { + return compare( + leftValue, null, + operator, null, + rightValue, null, + null, false, + false, false, false, + env); + } + + /** + * Same as {@link #compare(TemplateModel, int, TemplateModel, Environment)}, but if the two types are incompatible, + * they are treated as non-equal instead of throwing an exception. Comparing dates of different types will + * still throw an exception, however. + */ + static boolean compareLenient( + TemplateModel leftValue, int operator, TemplateModel rightValue, + Environment env) throws TemplateException { + return compare( + leftValue, null, + operator, null, + rightValue, null, + null, false, + true, false, false, + env); + } + + private static final String VALUE_OF_THE_COMPARISON_IS_UNKNOWN_DATE_LIKE + = "value of the comparison is a date-like value where " + + "it's not known if it's a date (no time part), time, or date-time, " + + "and thus can't be used in a comparison."; + + /** + * @param leftExp {@code null} is allowed, but may results in less helpful error messages + * @param operator one of the {@code COMP_OP_...} constants, like {@link #CMP_OP_EQUALS}. + * @param operatorString can be null {@code null}; the actual operator used, used for more accurate error message. + * @param rightExp {@code null} is allowed, but may results in less helpful error messages + * @param defaultBlamed {@code null} allowed; the expression to which the error will point to if something goes + * wrong that is not specific to the left or right side expression, or if that expression is {@code null}. + * @param typeMismatchMeansNotEqual If the two types are incompatible, they are treated as non-equal instead + * of throwing an exception. Comparing dates of different types will still throw an exception, however. + * @param leftNullReturnsFalse if {@code true}, a {@code null} left value will not cause exception, but make the + * expression {@code false}. + * @param rightNullReturnsFalse if {@code true}, a {@code null} right value will not cause exception, but make the + * expression {@code false}. + */ + static boolean compare( + TemplateModel leftValue, ASTExpression leftExp, + int operator, String operatorString, + TemplateModel rightValue, ASTExpression rightExp, + ASTExpression defaultBlamed, boolean quoteOperandsInErrors, + boolean typeMismatchMeansNotEqual, + boolean leftNullReturnsFalse, boolean rightNullReturnsFalse, + Environment env) throws TemplateException { + if (leftValue == null) { + if (leftNullReturnsFalse) { + return false; + } else { + if (leftExp != null) { + throw InvalidReferenceException.getInstance(leftExp, env); + } else { + throw new _MiscTemplateException(defaultBlamed, env, + "The left operand of the comparison was undefined or null."); + } + } + } + + if (rightValue == null) { + if (rightNullReturnsFalse) { + return false; + } else { + if (rightExp != null) { + throw InvalidReferenceException.getInstance(rightExp, env); + } else { + throw new _MiscTemplateException(defaultBlamed, env, + "The right operand of the comparison was undefined or null."); + } + } + } + + final int cmpResult; + if (leftValue instanceof TemplateNumberModel && rightValue instanceof TemplateNumberModel) { + Number leftNum = _EvalUtil.modelToNumber((TemplateNumberModel) leftValue, leftExp); + Number rightNum = _EvalUtil.modelToNumber((TemplateNumberModel) rightValue, rightExp); + ArithmeticEngine ae = + env != null + ? env.getArithmeticEngine() + : (leftExp != null + ? leftExp.getTemplate().getArithmeticEngine() + : ArithmeticEngine.BIGDECIMAL_ENGINE); + try { + cmpResult = ae.compareNumbers(leftNum, rightNum); + } catch (RuntimeException e) { + throw new _MiscTemplateException(defaultBlamed, e, env, + "Unexpected error while comparing two numbers: ", e); + } + } else if (leftValue instanceof TemplateDateModel && rightValue instanceof TemplateDateModel) { + TemplateDateModel leftDateModel = (TemplateDateModel) leftValue; + TemplateDateModel rightDateModel = (TemplateDateModel) rightValue; + + int leftDateType = leftDateModel.getDateType(); + int rightDateType = rightDateModel.getDateType(); + + if (leftDateType == TemplateDateModel.UNKNOWN || rightDateType == TemplateDateModel.UNKNOWN) { + String sideName; + ASTExpression sideExp; + if (leftDateType == TemplateDateModel.UNKNOWN) { + sideName = "left"; + sideExp = leftExp; + } else { + sideName = "right"; + sideExp = rightExp; + } + + throw new _MiscTemplateException(sideExp != null ? sideExp : defaultBlamed, env, + "The ", sideName, " ", VALUE_OF_THE_COMPARISON_IS_UNKNOWN_DATE_LIKE); + } + + if (leftDateType != rightDateType) { + throw new _MiscTemplateException(defaultBlamed, env, + "Can't compare dates of different types. Left date type is ", + TemplateDateModel.TYPE_NAMES.get(leftDateType), ", right date type is ", + TemplateDateModel.TYPE_NAMES.get(rightDateType), "."); + } + + Date leftDate = _EvalUtil.modelToDate(leftDateModel, leftExp); + Date rightDate = _EvalUtil.modelToDate(rightDateModel, rightExp); + cmpResult = leftDate.compareTo(rightDate); + } else if (leftValue instanceof TemplateScalarModel && rightValue instanceof TemplateScalarModel) { + if (operator != CMP_OP_EQUALS && operator != CMP_OP_NOT_EQUALS) { + throw new _MiscTemplateException(defaultBlamed, env, + "Can't use operator \"", cmpOpToString(operator, operatorString), "\" on string values."); + } + String leftString = _EvalUtil.modelToString((TemplateScalarModel) leftValue, leftExp, env); + String rightString = _EvalUtil.modelToString((TemplateScalarModel) rightValue, rightExp, env); + // FIXME NBC: Don't use the Collator here. That's locale-specific, but ==/!= should not be. + cmpResult = env.getCollator().compare(leftString, rightString); + } else if (leftValue instanceof TemplateBooleanModel && rightValue instanceof TemplateBooleanModel) { + if (operator != CMP_OP_EQUALS && operator != CMP_OP_NOT_EQUALS) { + throw new _MiscTemplateException(defaultBlamed, env, + "Can't use operator \"", cmpOpToString(operator, operatorString), "\" on boolean values."); + } + boolean leftBool = ((TemplateBooleanModel) leftValue).getAsBoolean(); + boolean rightBool = ((TemplateBooleanModel) rightValue).getAsBoolean(); + cmpResult = (leftBool ? 1 : 0) - (rightBool ? 1 : 0); + } else { + if (typeMismatchMeansNotEqual) { + if (operator == CMP_OP_EQUALS) { + return false; + } else if (operator == CMP_OP_NOT_EQUALS) { + return true; + } + // Falls through + } + throw new _MiscTemplateException(defaultBlamed, env, + "Can't compare values of these types. ", + "Allowed comparisons are between two numbers, two strings, two dates, or two booleans.\n", + "Left hand operand ", + (quoteOperandsInErrors && leftExp != null + ? new Object[] { "(", new _DelayedGetCanonicalForm(leftExp), ") value " } + : ""), + "is ", new _DelayedAOrAn(new _DelayedFTLTypeDescription(leftValue)), ".\n", + "Right hand operand ", + (quoteOperandsInErrors && rightExp != null + ? new Object[] { "(", new _DelayedGetCanonicalForm(rightExp), ") value " } + : ""), + "is ", new _DelayedAOrAn(new _DelayedFTLTypeDescription(rightValue)), + "."); + } + + switch (operator) { + case CMP_OP_EQUALS: return cmpResult == 0; + case CMP_OP_NOT_EQUALS: return cmpResult != 0; + case CMP_OP_LESS_THAN: return cmpResult < 0; + case CMP_OP_GREATER_THAN: return cmpResult > 0; + case CMP_OP_LESS_THAN_EQUALS: return cmpResult <= 0; + case CMP_OP_GREATER_THAN_EQUALS: return cmpResult >= 0; + default: throw new BugException("Unsupported comparator operator code: " + operator); + } + } + + private static String cmpOpToString(int operator, String operatorString) { + if (operatorString != null) { + return operatorString; + } else { + switch (operator) { + case CMP_OP_EQUALS: return "equals"; + case CMP_OP_NOT_EQUALS: return "not-equals"; + case CMP_OP_LESS_THAN: return "less-than"; + case CMP_OP_GREATER_THAN: return "greater-than"; + case CMP_OP_LESS_THAN_EQUALS: return "less-than-equals"; + case CMP_OP_GREATER_THAN_EQUALS: return "greater-than-equals"; + default: return "???"; + } + } + } + + /** + * Converts a value to plain text {@link String}, or a {@link TemplateMarkupOutputModel} if that's what the + * {@link TemplateValueFormat} involved produces. + * + * @param seqTip + * Tip to display if the value type is not coercable, but it's sequence or collection. + * + * @return Never {@code null} + */ + static Object coerceModelToStringOrMarkup(TemplateModel tm, ASTExpression exp, String seqTip, Environment env) + throws TemplateException { + return coerceModelToStringOrMarkup(tm, exp, false, seqTip, env); + } + + /** + * @return {@code null} if the {@code returnNullOnNonCoercableType} parameter is {@code true}, and the coercion is + * not possible, because of the type is not right for it. + * + * @see #coerceModelToStringOrMarkup(TemplateModel, ASTExpression, String, Environment) + */ + static Object coerceModelToStringOrMarkup( + TemplateModel tm, ASTExpression exp, boolean returnNullOnNonCoercableType, String seqTip, Environment env) + throws TemplateException { + if (tm instanceof TemplateNumberModel) { + TemplateNumberModel tnm = (TemplateNumberModel) tm; + TemplateNumberFormat format = env.getTemplateNumberFormat(exp, false); + try { + return assertFormatResultNotNull(format.format(tnm)); + } catch (TemplateValueFormatException e) { + throw MessageUtil.newCantFormatNumberException(format, exp, e, false); + } + } else if (tm instanceof TemplateDateModel) { + TemplateDateModel tdm = (TemplateDateModel) tm; + TemplateDateFormat format = env.getTemplateDateFormat(tdm, exp, false); + try { + return assertFormatResultNotNull(format.format(tdm)); + } catch (TemplateValueFormatException e) { + throw MessageUtil.newCantFormatDateException(format, exp, e, false); + } + } else if (tm instanceof TemplateMarkupOutputModel) { + return tm; + } else { + return coerceModelToTextualCommon(tm, exp, seqTip, true, returnNullOnNonCoercableType, env); + } + } + + /** + * Like {@link #coerceModelToStringOrMarkup(TemplateModel, ASTExpression, String, Environment)}, but gives error + * if the result is markup. This is what you normally use where markup results can't be used. + * + * @param seqTip + * Tip to display if the value type is not coercable, but it's sequence or collection. + * + * @return Never {@code null} + */ + static String coerceModelToStringOrUnsupportedMarkup( + TemplateModel tm, ASTExpression exp, String seqTip, Environment env) + throws TemplateException { + if (tm instanceof TemplateNumberModel) { + TemplateNumberModel tnm = (TemplateNumberModel) tm; + TemplateNumberFormat format = env.getTemplateNumberFormat(exp, false); + try { + return ensureFormatResultString(format.format(tnm), exp, env); + } catch (TemplateValueFormatException e) { + throw MessageUtil.newCantFormatNumberException(format, exp, e, false); + } + } else if (tm instanceof TemplateDateModel) { + TemplateDateModel tdm = (TemplateDateModel) tm; + TemplateDateFormat format = env.getTemplateDateFormat(tdm, exp, false); + try { + return ensureFormatResultString(format.format(tdm), exp, env); + } catch (TemplateValueFormatException e) { + throw MessageUtil.newCantFormatDateException(format, exp, e, false); + } + } else { + return coerceModelToTextualCommon(tm, exp, seqTip, false, false, env); + } + } + + /** + * Converts a value to plain text {@link String}, even if the {@link TemplateValueFormat} involved normally produces + * markup. This should be used rarely, where the user clearly intend to use the plain text variant of the format. + * + * @param seqTip + * Tip to display if the value type is not coercable, but it's sequence or collection. + * + * @return Never {@code null} + */ + static String coerceModelToPlainText(TemplateModel tm, ASTExpression exp, String seqTip, + Environment env) throws TemplateException { + if (tm instanceof TemplateNumberModel) { + return assertFormatResultNotNull(env.formatNumberToPlainText((TemplateNumberModel) tm, exp, false)); + } else if (tm instanceof TemplateDateModel) { + return assertFormatResultNotNull(env.formatDateToPlainText((TemplateDateModel) tm, exp, false)); + } else { + return coerceModelToTextualCommon(tm, exp, seqTip, false, false, env); + } + } + + /** + * @param tm + * If {@code null} that's an exception + * + * @param supportsTOM + * Whether the caller {@code coerceModelTo...} method could handle a {@link TemplateMarkupOutputModel}. + * + * @return Never {@code null} + */ + private static String coerceModelToTextualCommon( + TemplateModel tm, ASTExpression exp, String seqHint, boolean supportsTOM, boolean returnNullOnNonCoercableType, + Environment env) + throws TemplateException { + if (tm instanceof TemplateScalarModel) { + return modelToString((TemplateScalarModel) tm, exp, env); + } else if (tm == null) { + if (exp != null) { + throw InvalidReferenceException.getInstance(exp, env); + } else { + throw new InvalidReferenceException( + "Null/missing value (no more informatoin avilable)", + env); + } + } else if (tm instanceof TemplateBooleanModel) { + // [FM3] This should be before TemplateScalarModel, but automatic boolean-to-string is only non-error since + // 2.3.20, so to keep backward compatibility we couldn't insert this before TemplateScalarModel. + boolean booleanValue = ((TemplateBooleanModel) tm).getAsBoolean(); + return env.formatBoolean(booleanValue, false); + } else { + if (returnNullOnNonCoercableType) { + return null; + } + if (seqHint != null && (tm instanceof TemplateSequenceModel || tm instanceof TemplateCollectionModel)) { + if (supportsTOM) { + throw new NonStringOrTemplateOutputException(exp, tm, seqHint, env); + } else { + throw new NonStringException(exp, tm, seqHint, env); + } + } else { + if (supportsTOM) { + throw new NonStringOrTemplateOutputException(exp, tm, env); + } else { + throw new NonStringException(exp, tm, env); + } + } + } + } + + private static String ensureFormatResultString(Object formatResult, ASTExpression exp, Environment env) + throws NonStringException { + if (formatResult instanceof String) { + return (String) formatResult; + } + + assertFormatResultNotNull(formatResult); + + TemplateMarkupOutputModel mo = (TemplateMarkupOutputModel) formatResult; + _ErrorDescriptionBuilder desc = new _ErrorDescriptionBuilder( + "Value was formatted to convert it to string, but the result was markup of ouput format ", + new _DelayedJQuote(mo.getOutputFormat()), ".") + .tip("Use value?string to force formatting to plain text.") + .blame(exp); + throw new NonStringException(null, desc); + } + + static String assertFormatResultNotNull(String r) { + if (r != null) { + return r; + } + throw new NullPointerException("TemplateValueFormatter result can't be null"); + } + + static Object assertFormatResultNotNull(Object r) { + if (r != null) { + return r; + } + throw new NullPointerException("TemplateValueFormatter result can't be null"); + } + + static TemplateMarkupOutputModel concatMarkupOutputs(ASTNode parent, TemplateMarkupOutputModel leftMO, + TemplateMarkupOutputModel rightMO) throws TemplateException { + MarkupOutputFormat leftOF = leftMO.getOutputFormat(); + MarkupOutputFormat rightOF = rightMO.getOutputFormat(); + if (rightOF != leftOF) { + String rightPT; + String leftPT; + if ((rightPT = rightOF.getSourcePlainText(rightMO)) != null) { + return leftOF.concat(leftMO, leftOF.fromPlainTextByEscaping(rightPT)); + } else if ((leftPT = leftOF.getSourcePlainText(leftMO)) != null) { + return rightOF.concat(rightOF.fromPlainTextByEscaping(leftPT), rightMO); + } else { + Object[] message = { "Concatenation left hand operand is in ", new _DelayedToString(leftOF), + " format, while the right hand operand is in ", new _DelayedToString(rightOF), + ". Conversion to common format wasn't possible." }; + if (parent instanceof ASTExpression) { + throw new _MiscTemplateException((ASTExpression) parent, message); + } else { + throw new _MiscTemplateException(message); + } + } + } else { + return leftOF.concat(leftMO, rightMO); + } + } + + /** + * Returns an {@link ArithmeticEngine} even if {@code env} is {@code null}, because we are in parsing phase. + */ + static ArithmeticEngine getArithmeticEngine(Environment env, ASTNode tObj) { + return env != null + ? env.getArithmeticEngine() + : tObj.getTemplate().getParserConfiguration().getArithmeticEngine(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef968757/src/main/java/org/apache/freemarker/core/valueformat/InvalidFormatParametersException.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/valueformat/InvalidFormatParametersException.java b/src/main/java/org/apache/freemarker/core/valueformat/InvalidFormatParametersException.java new file mode 100644 index 0000000..d7502a4 --- /dev/null +++ b/src/main/java/org/apache/freemarker/core/valueformat/InvalidFormatParametersException.java @@ -0,0 +1,37 @@ +/* + * 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.valueformat; + +/** + * Used when creating {@link TemplateDateFormat}-s and {@link TemplateNumberFormat}-s to indicate that the parameters + * part of the format string (like some kind of pattern) is malformed. + * + * @since 2.3.24 + */ +public final class InvalidFormatParametersException extends InvalidFormatStringException { + + public InvalidFormatParametersException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidFormatParametersException(String message) { + this(message, null); + } + +}
