Java tutorial
/* * Copyright 2012 Google Inc. * * 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 com.google.template.soy.i18ndirectives; import static com.google.template.soy.shared.restricted.SoyJavaRuntimeFunctionUtils.toSoyData; import java.util.List; import java.util.Locale; import java.util.Set; import org.apache.commons.lang3.StringEscapeUtils; import com.google.common.collect.ImmutableSet; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.template.soy.data.SoyData; import com.google.template.soy.jssrc.restricted.JsExpr; import com.google.template.soy.jssrc.restricted.SoyJsSrcPrintDirective; import com.google.template.soy.shared.restricted.ApiCallScopeBindingAnnotations.LocaleString; import com.google.template.soy.tofu.restricted.SoyAbstractTofuPrintDirective; import com.ibm.icu.text.NumberFormat; /** * A directive that formats an input number based on Locale of the current SoyMsgBundle. * It takes a single argument : an optional lower-case string describing the type of format to * apply, which can be one of 'decimal', 'currency', 'percent', or 'scientific'. If the argument is * not provided, the default, 'decimal' will be used. * * @author Jeff Craig */ class FormatNumDirective extends SoyAbstractTofuPrintDirective implements SoyJsSrcPrintDirective { /** * Provide the current Locale string. * * Note that this Locale value is only used in the Java environment. Closure does not provide a * clear mechanism to override the NumberFormat defined when the NumberFormat module loads. This * is probably not a significant loss of functionality, since the primary reason to inject the * LocaleString is because the Java VM's default Locale may not be the same as the desired Locale * for the page, while in the JavaScript environment, the value of goog.LOCALE should reliably * indicate which Locale Soy should use. */ private Provider<String> localeStringProvider; @Inject FormatNumDirective(@LocaleString Provider<String> localeStringProvider) { this.localeStringProvider = localeStringProvider; } @Override public String getName() { return "|formatNum"; } @Override public Set<Integer> getValidArgsSizes() { return ImmutableSet.of(1); } @Override public boolean shouldCancelAutoescape() { return false; } @Override public SoyData apply(SoyData value, List<SoyData> args) { Locale locale = I18nUtils.parseLocale(localeStringProvider.get()); NumberFormat instance; String formatType = args.isEmpty() ? "decimal" : args.get(0).stringValue(); if (formatType.equals("decimal")) { instance = NumberFormat.getInstance(locale); } else if (formatType.equals("percent")) { instance = NumberFormat.getPercentInstance(locale); } else if (formatType.equals("currency")) { instance = NumberFormat.getCurrencyInstance(locale); } else if (formatType.equals("scientific")) { instance = NumberFormat.getScientificInstance(locale); } else { throw new IllegalArgumentException(String.format("Unrecognized Number Format Type: {0}", formatType)); } return toSoyData(StringEscapeUtils.escapeHtml4(instance.format(Float.parseFloat(value.stringValue())))); } @Override public JsExpr applyForJsSrc(JsExpr value, List<JsExpr> args) { String numberFormatNameJsExprText; if (args.isEmpty()) { numberFormatNameJsExprText = "'DECIMAL'"; } else { numberFormatNameJsExprText = "(" + args.get(0).getText() + ").toUpperCase()"; } String numberFormatDecl = "goog.i18n.NumberFormat.Format[" + numberFormatNameJsExprText + "]"; return new JsExpr("(new goog.i18n.NumberFormat(" + numberFormatDecl + ")).format(" + value.getText() + ")", Integer.MAX_VALUE); } }