/*
* Copyright 2014 Attila Szegedi, Daniel Dekany, Jonathan Revusky
*
* Licensed 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 freemarker.core;
import java.util.Locale;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNumberModel;
import freemarker.template.utility.NumberUtil;
import freemarker.template.utility.StringUtil;
public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactory {
public static final BaseNTemplateNumberFormatFactory INSTANCE = new BaseNTemplateNumberFormatFactory();
private BaseNTemplateNumberFormatFactory() {
// Defined to decrease visibility
}
@Override
public TemplateNumberFormat get(String params, Locale locale, Environment env)
throws InvalidFormatParametersException {
TemplateNumberFormat fallbackFormat;
{
int barIdx = params.indexOf('|');
if (barIdx != -1) {
String fallbackFormatStr = params.substring(barIdx + 1);
params = params.substring(0, barIdx);
try {
fallbackFormat = env.getTemplateNumberFormat(fallbackFormatStr, locale);
} catch (InvalidFormatStringException e) {
throw new InvalidFormatParametersException(
"Couldn't get the fallback number format (specified after the \"|\"), "
+ StringUtil.jQuote(fallbackFormatStr) + ". Reason: " + e.getMessage(),
e);
}
} else {
fallbackFormat = null;
}
}
int base;
try {
base = Integer.parseInt(params);
} catch (NumberFormatException e) {
if (params.length() == 0) {
throw new InvalidFormatParametersException(
"A format parameter is required, which specifies the numerical system base.");
}
throw new InvalidFormatParametersException(
"The format paramter must be an integer, but was (shown quoted): " + StringUtil.jQuote(params));
}
return new BaseNTemplateNumberFormat(base, fallbackFormat);
}
private static class BaseNTemplateNumberFormat extends TemplateNumberFormat {
private final int base;
private final TemplateNumberFormat fallbackFormat;
private BaseNTemplateNumberFormat(int base, TemplateNumberFormat fallbackFormat) {
this.base = base;
this.fallbackFormat = fallbackFormat;
}
@Override
public String format(TemplateNumberModel numberModel)
throws UnformattableNumberException, TemplateModelException {
Number n = TemplateFormatUtil.getNonNullNumber(numberModel);
try {
return Integer.toString(NumberUtil.toIntExact(n), base);
} catch (ArithmeticException e) {
if (fallbackFormat == null) {
throw new UnformattableNumberException(
n + " doesn't fit into an int, and there was no fallback format specified.");
} else {
return fallbackFormat.format(numberModel);
}
}
}
@Override
public <MO extends TemplateMarkupOutputModel> MO format(TemplateNumberModel dateModel,
MarkupOutputFormat<MO> outputFormat) throws UnformattableNumberException, TemplateModelException {
return null;
}
@Override
public boolean isLocaleBound() {
return false;
}
@Override
public String getDescription() {
return "hexadecimal int";
}
}
}