Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1827)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/payments/CurrencyStringFormatter.java

Issue 1904553003: Java implementation of PaymentRequest mojo service (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/payments/CurrencyStringFormatter.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/CurrencyStringFormatter.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/CurrencyStringFormatter.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf61d9dfc737c9388f539332040b1baa6320513f
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/CurrencyStringFormatter.java
@@ -0,0 +1,147 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.payments;
+
+import java.text.DecimalFormatSymbols;
+import java.util.Currency;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Formatter for currency strings that can be too large to parse into numbers.
+ * https://w3c.github.io/browser-payment-api/specs/paymentrequest.html#currencyamount
+ */
+public class CurrencyStringFormatter {
+ // Amount value pattern and capture group numbers.
+ private static final String AMOUNT_VALUE_PATTERN = "^(-?)([0-9]+)(\\.([0-9]+))?$";
+ private static final int OPTIONAL_NEGATIVE_GROUP = 1;
+ private static final int DIGITS_BETWEEN_NEGATIVE_AND_PERIOD_GROUP = 2;
+ private static final int DIGITS_AFTER_PERIOD_GROUP = 4;
+
+ // Amount currency code pattern.
+ private static final String AMOUNT_CURRENCY_CODE_PATTERN = "^[A-Z]{3}$";
+
+ // Formatting constants.
+ private static final int DIGIT_GROUPING_SIZE = 3;
+
+ private final Pattern mAmountValuePattern;
+ private final Pattern mAmountCurrencyCodePattern;
+
+ /**
+ * The symbol for the currency specified on the bill. For example, the symbol for "USD" is "$".
+ */
+ private final String mCurrencySymbol;
+
+ /**
+ * The number grouping separator for the current locale. For example, "," in US. 3-digit groups
+ * are assumed.
+ */
+ private final char mGroupingSeparator;
+
+ /**
+ * The decimal separator for the current locale. For example, "." in US and "," in France.
+ */
+ private final char mMonetaryDecimalSeparator;
+
+ /**
+ * Builds the formatter for the given currency code and the current user locale.
+ *
+ * @param currencyCode The currency code. Most commonly, this follows ISO 4217 format: 3 upper
+ * case ASCII letters. For example, "USD". Format is not restricted. Should
+ * not be null.
+ * @param userLocale User's current locale. Should not be null.
+ */
+ public CurrencyStringFormatter(String currencyCode, Locale userLocale) {
+ assert currencyCode != null : "currencyCode should not be null";
+ assert userLocale != null : "userLocale should not be null";
+
+ mAmountValuePattern = Pattern.compile(AMOUNT_VALUE_PATTERN);
+ mAmountCurrencyCodePattern = Pattern.compile(AMOUNT_CURRENCY_CODE_PATTERN);
+
+ String currencySymbol;
+ try {
+ currencySymbol = Currency.getInstance(currencyCode).getSymbol();
+ } catch (IllegalArgumentException e) {
+ // The spec does not limit the currencies to official ISO 4217 currency code list, which
+ // is used by java.util.Currency. For example, "BTX" (bitcoin) is not an official ISO
+ // 4217 currency code, but is allowed by the spec.
+ currencySymbol = currencyCode;
+ }
+ mCurrencySymbol = currencySymbol;
+
+ // Use the symbols from user's current locale. For example, use "," for decimal separator in
+ // France, even if paying in "USD".
+ DecimalFormatSymbols symbols = new DecimalFormatSymbols(userLocale);
+ mGroupingSeparator = symbols.getGroupingSeparator();
+ mMonetaryDecimalSeparator = symbols.getMonetaryDecimalSeparator();
+ }
+
+ /**
+ * Returns true if the amount value string is in valid format.
+ *
+ * @param amountValue The number to check for validity.
+ * @return Whether the number is in valid format.
+ */
+ public boolean isValidAmountValue(String amountValue) {
+ return amountValue != null && mAmountValuePattern.matcher(amountValue).matches();
+ }
+
+ /**
+ * Returns true if the currency code string is in valid format.
+ *
+ * @param amountCurrencyCode The currency code to check for validity.
+ * @return Whether the currency code is in valid format.
+ */
+ public boolean isValidAmountCurrencyCode(String amountCurrencyCode) {
+ return amountCurrencyCode != null
+ && mAmountCurrencyCodePattern.matcher(amountCurrencyCode).matches();
+ }
+
+ /**
+ * Formats the currency string for display. Does not parse the string into a number, because it
+ * might be too large. The number is formatted for the current locale and follows the symbol of
+ * the currency code.
+ *
+ * @param amountValue The number to format. Should be in "^-?[0-9]+(\.[0-9]+)?$" format. Should
+ * not be null.
+ * @return The currency symbol followed by a space and the formatted number.
+ */
+ public String format(String amountValue) {
+ assert amountValue != null : "amountValue should not be null";
+
+ Matcher m = mAmountValuePattern.matcher(amountValue);
+
+ // Required to capture the groups.
+ boolean matches = m.matches();
+ assert matches;
+
+ StringBuilder result = new StringBuilder(mCurrencySymbol);
+ result.append(" ");
+ result.append(m.group(OPTIONAL_NEGATIVE_GROUP));
+ int digitStart = result.length();
+
+ result.append(m.group(DIGITS_BETWEEN_NEGATIVE_AND_PERIOD_GROUP));
+ for (int i = result.length() - DIGIT_GROUPING_SIZE; i > digitStart;
+ i -= DIGIT_GROUPING_SIZE) {
+ result.insert(i, mGroupingSeparator);
+ }
+
+ result.append(mMonetaryDecimalSeparator);
+
+ String decimals = m.group(DIGITS_AFTER_PERIOD_GROUP);
+ int numberOfDecimals = 0;
+ if (decimals != null) {
+ numberOfDecimals = decimals.length();
+ result.append(decimals);
+ }
+
+ for (int i = numberOfDecimals; i < 2; i++) {
+ result.append("0");
+ }
+
+ return result.toString();
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698