1 /*
  2  * phoneloc.js - Represent a phone locale object.
  3  *
  4  * Copyright © 2014-2015, 2018, JEDLSoft
  5  *
  6  * Licensed under the Apache License, Version 2.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at
  9  *
 10  *     http://www.apache.org/licenses/LICENSE-2.0
 11  *
 12  * Unless required by applicable law or agreed to in writing, software
 13  * distributed under the License is distributed on an "AS IS" BASIS,
 14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  *
 16  * See the License for the specific language governing permissions and
 17  * limitations under the License.
 18  */
 19 
 20 // !data phoneloc
 21 
 22 var ilib = require("./ilib.js");
 23 var Utils = require("./Utils.js");
 24 var Locale = require("./Locale.js");
 25 
 26 /**
 27  * @class
 28  * Extension of the locale class that has extra methods to map various numbers
 29  * related to phone number parsing.
 30  *
 31  * @param {Object} options Options that govern how this phone locale works
 32  *
 33  * @private
 34  * @constructor
 35  * @extends Locale
 36  */
 37 var PhoneLocale = function(options) {
 38     var region,
 39         mcc,
 40         cc,
 41         sync = true,
 42         loadParams = {},
 43         locale;
 44 
 45     locale = (options && options.locale) || ilib.getLocale();
 46 
 47     this.parent.call(this, locale);
 48 
 49     region = this.region;
 50 
 51     if (options) {
 52         if (typeof(options.mcc) !== 'undefined') {
 53             mcc = options.mcc;
 54         }
 55 
 56         if (typeof(options.countryCode) !== 'undefined') {
 57             cc = options.countryCode;
 58         }
 59 
 60         if (typeof(options.sync) !== 'undefined') {
 61             sync = !!options.sync;
 62         }
 63 
 64         if (options.loadParams) {
 65             loadParams = options.loadParams;
 66         }
 67     }
 68 
 69     Utils.loadData({
 70         name: "phoneloc.json",
 71         object: "PhoneLocale",
 72         nonlocale: true,
 73         sync: sync,
 74         loadParams: loadParams,
 75         callback: ilib.bind(this, function (data) {
 76             /** @type {{mcc2reg:Object.<string,string>,cc2reg:Object.<string,string>,reg2cc:Object.<string,string>,area2reg:Object.<string,string>}} */
 77             this.mappings = data;
 78 
 79             if (typeof(mcc) !== 'undefined') {
 80                 region = this.mappings.mcc2reg[mcc];
 81             }
 82 
 83             if (typeof(cc) !== 'undefined') {
 84                 region = this.mappings.cc2reg[cc];
 85             }
 86 
 87             if (!region) {
 88                 region = "XX";
 89             }
 90 
 91             this.region = this._normPhoneReg(region);
 92             this._genSpec();
 93 
 94             if (options && typeof(options.onLoad) === 'function') {
 95                 options.onLoad(this);
 96             }
 97         })
 98     });
 99 };
100 
101 PhoneLocale.prototype = new Locale();
102 PhoneLocale.prototype.parent = Locale;
103 PhoneLocale.prototype.constructor = PhoneLocale;
104 
105 /**
106  * Map a mobile carrier code to a region code.
107  *
108  * @static
109  * @package
110  * @param {string|undefined} mcc the MCC to map
111  * @return {string|undefined} the region code
112  */
113 
114 PhoneLocale.prototype._mapMCCtoRegion = function(mcc) {
115     if (!mcc) {
116         return undefined;
117     }
118     return this.mappings.mcc2reg && this.mappings.mcc2reg[mcc] || "XX";
119 };
120 
121 /**
122  * Map a country code to a region code.
123  *
124  * @static
125  * @package
126  * @param {string|undefined} cc the country code to map
127  * @return {string|undefined} the region code
128  */
129 PhoneLocale.prototype._mapCCtoRegion = function(cc) {
130     if (!cc) {
131         return undefined;
132     }
133     return this.mappings.cc2reg && this.mappings.cc2reg[cc] || "XX";
134 };
135 
136 /**
137  * Map a region code to a country code.
138  *
139  * @static
140  * @package
141  * @param {string|undefined} region the region code to map
142  * @return {string|undefined} the country code
143  */
144 PhoneLocale.prototype._mapRegiontoCC = function(region) {
145     if (!region) {
146         return undefined;
147     }
148     return this.mappings.reg2cc && this.mappings.reg2cc[region] || "0";
149 };
150 
151 /**
152  * Map a country code to a region code.
153  *
154  * @static
155  * @package
156  * @param {string|undefined} cc the country code to map
157  * @param {string|undefined} area the area code within the country code's numbering plan
158  * @return {string|undefined} the region code
159  */
160 PhoneLocale.prototype._mapAreatoRegion = function(cc, area) {
161     if (!cc) {
162         return undefined;
163     }
164     if (cc in this.mappings.area2reg) {
165         return this.mappings.area2reg[cc][area] || this.mappings.area2reg[cc]["default"];
166     } else {
167         return this.mappings.cc2reg[cc];
168     }
169 };
170 
171 /**
172  * Return the region that controls the dialing plan in the given
173  * region. (ie. the "normalized phone region".)
174  *
175  * @static
176  * @package
177  * @param {string} region the region code to normalize
178  * @return {string} the normalized region code
179  */
180 PhoneLocale.prototype._normPhoneReg = function(region) {
181     var norm;
182 
183     // Map all NANP regions to the right region, so that they get parsed using the
184     // correct state table
185     switch (region) {
186         case "US": // usa
187         case "CA": // canada
188         case "AG": // antigua and barbuda
189         case "BS": // bahamas
190         case "BB": // barbados
191         case "DM": // dominica
192         case "DO": // dominican republic
193         case "GD": // grenada
194         case "JM": // jamaica
195         case "KN": // st. kitts and nevis
196         case "LC": // st. lucia
197         case "VC": // st. vincent and the grenadines
198         case "TT": // trinidad and tobago
199         case "AI": // anguilla
200         case "BM": // bermuda
201         case "VG": // british virgin islands
202         case "KY": // cayman islands
203         case "MS": // montserrat
204         case "TC": // turks and caicos
205         case "AS": // American Samoa
206         case "VI": // Virgin Islands, U.S.
207         case "PR": // Puerto Rico
208         case "MP": // Northern Mariana Islands
209         case "T:": // East Timor
210         case "GU": // Guam
211             norm = "US";
212             break;
213 
214         // these all use the Italian dialling plan
215         case "IT": // italy
216         case "SM": // san marino
217         case "VA": // vatican city
218             norm = "IT";
219             break;
220 
221         // all the French dependencies are on the French dialling plan
222         case "FR": // france
223         case "GF": // french guiana
224         case "MQ": // martinique
225         case "GP": // guadeloupe,
226         case "BL": // saint barthélemy
227         case "MF": // saint martin
228         case "RE": // réunion, mayotte
229             norm = "FR";
230             break;
231         default:
232             norm = region;
233             break;
234     }
235     return norm;
236 };
237 
238 module.exports = PhoneLocale;