1/*
2 * Copyright (C) 2011 The Libphonenumber Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.i18n.phonenumbers;
18
19import com.android.i18n.phonenumbers.Phonemetadata.PhoneMetadata;
20
21import java.util.regex.Pattern;
22
23/*
24 * Utility for international short phone numbers, such as short codes and emergency numbers. Note
25 * most commercial short numbers are not handled here, but by the PhoneNumberUtil.
26 *
27 * @author Shaopeng Jia
28 */
29public class ShortNumberUtil {
30
31  private final PhoneNumberUtil phoneUtil;
32
33  public ShortNumberUtil() {
34    phoneUtil = PhoneNumberUtil.getInstance();
35  }
36
37  // @VisibleForTesting
38  ShortNumberUtil(PhoneNumberUtil util) {
39    phoneUtil = util;
40  }
41
42  /**
43   * Returns true if the number might be used to connect to an emergency service in the given
44   * region.
45   *
46   * This method takes into account cases where the number might contain formatting, or might have
47   * additional digits appended (when it is okay to do that in the region specified).
48   *
49   * @param number  the phone number to test
50   * @param regionCode  the region where the phone number is being dialed
51   * @return  if the number might be used to connect to an emergency service in the given region.
52   */
53  public boolean connectsToEmergencyNumber(String number, String regionCode) {
54    return matchesEmergencyNumberHelper(number, regionCode, true /* allows prefix match */);
55  }
56
57  /**
58   * Returns true if the number exactly matches an emergency service number in the given region.
59   *
60   * This method takes into account cases where the number might contain formatting, but doesn't
61   * allow additional digits to be appended.
62   *
63   * @param number  the phone number to test
64   * @param regionCode  the region where the phone number is being dialed
65   * @return  if the number exactly matches an emergency services number in the given region.
66   */
67  public boolean isEmergencyNumber(String number, String regionCode) {
68    return matchesEmergencyNumberHelper(number, regionCode, false /* doesn't allow prefix match */);
69  }
70
71  private boolean matchesEmergencyNumberHelper(String number, String regionCode,
72      boolean allowPrefixMatch) {
73    number = PhoneNumberUtil.extractPossibleNumber(number);
74    if (PhoneNumberUtil.PLUS_CHARS_PATTERN.matcher(number).lookingAt()) {
75      // Returns false if the number starts with a plus sign. We don't believe dialing the country
76      // code before emergency numbers (e.g. +1911) works, but later, if that proves to work, we can
77      // add additional logic here to handle it.
78      return false;
79    }
80    PhoneMetadata metadata = phoneUtil.getMetadataForRegion(regionCode);
81    if (metadata == null || !metadata.hasEmergency()) {
82      return false;
83    }
84    Pattern emergencyNumberPattern =
85        Pattern.compile(metadata.getEmergency().getNationalNumberPattern());
86    String normalizedNumber = PhoneNumberUtil.normalizeDigitsOnly(number);
87    // In Brazil, it is impossible to append additional digits to an emergency number to dial the
88    // number.
89    return (!allowPrefixMatch || regionCode.equals("BR"))
90        ? emergencyNumberPattern.matcher(normalizedNumber).matches()
91        : emergencyNumberPattern.matcher(normalizedNumber).lookingAt();
92  }
93}
94