@Override
 public boolean handle(Object data) {
   super.handle(data);
   if (data == null) {
     return false;
   }
   try {
     PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
     IndicatorParameters indParameters = this.getParameters();
     TextParameters textParameters =
         indParameters == null ? null : indParameters.getTextParameter();
     String country = IndicatorHelper.getCountryCodeByParameter(textParameters);
     PhoneNumber phoneNumeber = phoneUtil.parse(data.toString(), country);
     // It only checks the length of phone numbers. In particular, it doesn't check starting digits
     // of the
     // number.
     if (phoneUtil.isPossibleNumber(phoneNumeber)) {
       this.possiblePhoneCount++;
       if (checkMustStoreCurrentRow() || this.checkMustStoreCurrentRow(drillDownValueCount)) {
         this.mustStoreRow = true;
       }
     }
   } catch (NumberParseException e) {
     return false;
   }
   return true;
 }
  /*
   * (non-Jsdoc)
   *
   * @see org.talend.dataquality.indicators.impl.IndicatorImpl#handle(java.lang.Object)
   */
  @Override
  public boolean handle(Object data) {
    super.handle(data);
    if (data == null) {
      return false;
    }
    PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
    // }

    // the parameter defualtRegion is null at here, it will get an region code when the data is
    // guaranteed to
    // start with a '+' followed by the country calling code. e.g. "+86 13521588311",
    // "+8613521588311",
    // "+86 1352 1588 311". or else, it will throw Exception and as a invalid Region Code.
    boolean parseSuccess = true;
    String regionCodeForNumber = null;
    try {
      PhoneNumber phhoneNum = phoneUtil.parse(data.toString(), null);
      regionCodeForNumber = phoneUtil.getRegionCodeForNumber(phhoneNum);
    } catch (NumberParseException e) {
      parseSuccess = false;
    }
    Set<String> supportedCountries = phoneUtil.getSupportedRegions();
    if (parseSuccess && supportedCountries.contains(regionCodeForNumber)) {
      this.validRegCount++;
      if (checkMustStoreCurrentRow() || checkMustStoreCurrentRow(drillDownValueCount)) {
        this.mustStoreRow = true;
      }
    }

    return true;
  }
 private boolean strictGooglePhoneValid(String phoneNumber) {
   try {
     Phonenumber.PhoneNumber usPhoneNumber = phoneUtil.parse(phoneNumber, "US");
     return phoneUtil.isValidNumber(usPhoneNumber);
   } catch (NumberParseException e) {
     log.error("NumberParseException was thrown: " + e.toString());
     return false;
   }
 }
Example #4
0
 protected PhoneNumber getPhoneNumber(final MultivaluedMap<String, String> data) {
   final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
   PhoneNumber phoneNumber = null;
   try {
     phoneNumber = phoneNumberUtil.parse(data.getFirst("PhoneNumber"), "US");
   } catch (final NumberParseException ignored) {
   }
   return phoneNumber;
 }
Example #5
0
  private long getThreadIdFor(IncomingMediaMessage retrieved)
      throws RecipientFormattingException, MmsException {
    if (retrieved.getGroupId() != null) {
      Recipients groupRecipients =
          RecipientFactory.getRecipientsFromString(context, retrieved.getGroupId(), true);
      return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipients);
    }

    String localNumber;
    Set<String> group = new HashSet<>();

    if (retrieved.getAddresses().getFrom() == null) {
      throw new MmsException("FROM value in PduHeaders did not exist.");
    }

    group.add(retrieved.getAddresses().getFrom());

    if (TextSecurePreferences.isPushRegistered(context)) {
      localNumber = TextSecurePreferences.getLocalNumber(context);
    } else {
      localNumber = ServiceUtil.getTelephonyManager(context).getLine1Number();
    }

    for (String cc : retrieved.getAddresses().getCc()) {
      PhoneNumberUtil.MatchType match;

      if (localNumber == null) match = PhoneNumberUtil.MatchType.NO_MATCH;
      else match = PhoneNumberUtil.getInstance().isNumberMatch(localNumber, cc);

      if (match == PhoneNumberUtil.MatchType.NO_MATCH
          || match == PhoneNumberUtil.MatchType.NOT_A_NUMBER) {
        group.add(cc);
      }
    }

    if (retrieved.getAddresses().getTo().size() > 1) {
      for (String to : retrieved.getAddresses().getTo()) {
        PhoneNumberUtil.MatchType match;

        if (localNumber == null) match = PhoneNumberUtil.MatchType.NO_MATCH;
        else match = PhoneNumberUtil.getInstance().isNumberMatch(localNumber, to);

        if (match == PhoneNumberUtil.MatchType.NO_MATCH
            || match == PhoneNumberUtil.MatchType.NOT_A_NUMBER) {
          group.add(to);
        }
      }
    }

    String recipientsList = Util.join(group, ",");
    Recipients recipients =
        RecipientFactory.getRecipientsFromString(context, recipientsList, false);

    return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
  }
Example #6
0
 public String remove_plus(String phoneNumber) {
   try {
     if (phoneNumber.charAt(0) == '+') {
       PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
       Phonenumber.PhoneNumber numberProto = phoneUtil.parse(phoneNumber, "");
       return "0" + String.valueOf(numberProto.getNationalNumber());
     } else {
       return phoneNumber;
     }
   } catch (Exception e) {
     return null;
   }
 }
 /**
  * Converts the phone number to E164 standard
  *
  * @param phone the phone number to convert
  * @return same number in E164 format
  */
 private String formatToE164(String phone) {
   PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
   Phonenumber.PhoneNumber numberProto = null;
   try {
     numberProto = phoneUtil.parse(phone, getUserCountry());
   } catch (NumberParseException e) {
     System.err.println("NumberParseException was thrown: " + e.toString());
   }
   String formatted = null;
   if (numberProto != null) {
     formatted = phoneUtil.format(numberProto, PhoneNumberUtil.PhoneNumberFormat.E164);
   }
   return (formatted != null ? formatted : phone.replaceAll("[^0-9+]+", ""));
 }
Example #8
0
  public static String isMobile(String mobile) {
    String phone = null;
    try {
      PhoneNumber pn = phoneUtil.parse(mobile, "CN");

      if (phoneUtil.isValidNumber(pn)) {
        phone = phoneUtil.format(pn, PhoneNumberFormat.E164).replace("+86", "");
        LOGGER.debug("phone util parse into cn : " + phone);
      }
    } catch (Exception e) {
      LOGGER.error("check mobile error! ", e);
    }

    return phone;
  }
 public void add(String regionCode) {
   CountryCode cc = new CountryCode();
   cc.regionCode = regionCode;
   cc.countryCode = PhoneNumberUtil.getInstance().getCountryCodeForRegion(regionCode);
   cc.regionName = NumberValidator.getRegionDisplayName(regionCode, Locale.getDefault());
   mData.add(cc);
 }
/** Created by vijay.polsani on 9/26/15. */
@Slf4j
public class UsPhoneValidationDecorator extends PhoneValidationDecorator {
  private static final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();

  public UsPhoneValidationDecorator(PhoneValidation decoratedPhoneValidation) {
    super(decoratedPhoneValidation);
  }

  @Override
  public boolean isPhoneNumberValid(String phoneNumber) {
    if (decoratedPhoneValidation.isPhoneNumberValid(phoneNumber))
      return strictGooglePhoneValid(phoneNumber);
    else return false;
  }

  private boolean strictGooglePhoneValid(String phoneNumber) {
    try {
      Phonenumber.PhoneNumber usPhoneNumber = phoneUtil.parse(phoneNumber, "US");
      return phoneUtil.isValidNumber(usPhoneNumber);
    } catch (NumberParseException e) {
      log.error("NumberParseException was thrown: " + e.toString());
      return false;
    }
  }
}
  /**
   * Compatibility method for {@link PhoneNumberUtil#getSupportedRegions()}. This was introduced
   * because crappy Honeycomb has an old version of libphonenumber, therefore Dalvik will insist on
   * we using it. In case getSupportedRegions doesn't exist, getSupportedCountries will be used.
   */
  @SuppressWarnings("unchecked")
  private Set<String> getSupportedRegions(PhoneNumberUtil util) {
    try {
      return (Set<String>) util.getClass().getMethod("getSupportedRegions").invoke(util);
    } catch (NoSuchMethodException e) {
      try {
        return (Set<String>) util.getClass().getMethod("getSupportedCountries").invoke(util);
      } catch (Exception helpme) {
        // ignored
      }
    } catch (Exception e) {
      // ignored
    }

    return new HashSet<String>();
  }
  private boolean checkInput() {
    mPhoneNumber = null;
    String phoneStr = null;

    // check name first
    mName = mNameText.getText().toString().trim();
    if (mName.length() == 0) {
      error(R.string.title_no_name, R.string.msg_no_name);
      return false;
    }

    PhoneNumberUtil util = PhoneNumberUtil.getInstance();
    CountryCode cc = (CountryCode) mCountryCode.getSelectedItem();
    if (!BuildConfig.DEBUG) {
      PhoneNumber phone;
      try {
        phone = util.parse(mPhone.getText().toString(), cc.regionCode);
        if (!util.isValidNumberForRegion(phone, cc.regionCode)) {
          throw new NumberParseException(
              ErrorType.INVALID_COUNTRY_CODE, "invalid number for region " + cc.regionCode);
        }
      } catch (NumberParseException e1) {
        error(R.string.title_invalid_number, R.string.msg_invalid_number);
        return false;
      }

      // check phone number format
      if (phone != null) {
        phoneStr = util.format(phone, PhoneNumberFormat.E164);
        if (!PhoneNumberUtils.isWellFormedSmsAddress(phoneStr)) {
          Log.i(TAG, "not a well formed SMS address");
        }
      }
    } else {
      phoneStr = String.format(Locale.US, "+%d%s", cc.countryCode, mPhone.getText().toString());
    }

    // phone is null - invalid number
    if (phoneStr == null) {
      Toast.makeText(this, R.string.warn_invalid_number, Toast.LENGTH_SHORT).show();
      return false;
    }

    Log.v(TAG, "Using phone number to register: " + phoneStr);
    mPhoneNumber = phoneStr;
    return true;
  }
Example #13
0
  public static String isPhoneNumber(String mobile) {
    String phone = null;
    try {
      LOGGER.debug("test phone number : " + mobile);
      PhoneNumber pn = phoneUtil.parse(mobile, "CN");

      if (phoneUtil.isValidNumber(pn)) {
        phone = phoneUtil.format(pn, PhoneNumberFormat.E164).replace("+86", "");
        LOGGER.debug("phone util parse into cn : " + phone);
      }
    } catch (NumberParseException e) {
      LOGGER.error("parse valid number! ", e);
    }

    if (phone == null) phone = mobile.replace("+", "");

    return phone;
  }
Example #14
0
 private void normalize(final MultivaluedMap<String, String> data)
     throws IllegalArgumentException {
   final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
   final String from = data.getFirst("From");
   if (!from.contains("@")) {
     // https://github.com/Mobicents/RestComm/issues/150 Don't complain in case of URIs in the From
     // header
     data.remove("From");
     try {
       data.putSingle(
           "From",
           phoneNumberUtil.format(phoneNumberUtil.parse(from, "US"), PhoneNumberFormat.E164));
     } catch (final NumberParseException exception) {
       throw new IllegalArgumentException(exception);
     }
   }
   final String to = data.getFirst("To");
   // Only try to normalize phone numbers.
   if (to.startsWith("client")) {
     if (to.split(":").length != 2) {
       throw new IllegalArgumentException(to + " is an invalid client identifier.");
     }
   } else if (!to.contains("@")) {
     data.remove("To");
     try {
       data.putSingle(
           "To", phoneNumberUtil.format(phoneNumberUtil.parse(to, "US"), PhoneNumberFormat.E164));
     } catch (final NumberParseException exception) {
       throw new IllegalArgumentException(exception);
     }
   }
   URI.create(data.getFirst("Url"));
 }
  public static Phonenumber.PhoneNumber getPhoneNumber(
      @Nullable String text, @Nullable Country country, boolean validateAgainstCountry) {
    if (country == null) {
      return null;
    }

    if (TextUtils.isEmpty(text)) {
      return null;
    }

    try {
      String region = country.getIsoCode().toUpperCase(Locale.US);
      Phonenumber.PhoneNumber number = PhoneNumberUtil.getInstance().parse(text, region);
      if (validateAgainstCountry
          && PhoneNumberUtil.getInstance().isValidNumberForRegion(number, region)) {
        return number;
      } else if (!validateAgainstCountry && PhoneNumberUtil.getInstance().isValidNumber(number)) {
        return number;
      }
    } catch (NumberParseException ignored) {
    }
    return null;
  }
Example #16
0
  public static @Nullable String getDeviceE164Number(Context context) {
    final String localNumber =
        ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number();
    final String countryIso = getSimCountryIso(context);
    final Integer countryCode = PhoneNumberUtil.getInstance().getCountryCodeForRegion(countryIso);

    if (TextUtils.isEmpty(localNumber)) return null;

    if (localNumber.startsWith("+")) return localNumber;
    else if (!TextUtils.isEmpty(countryIso))
      return PhoneNumberFormatter.formatE164(String.valueOf(countryCode), localNumber);
    else if (localNumber.length() == 10) return "+1" + localNumber;
    else return "+" + localNumber;
  }
public class LibphoneNumberOfflineGeocoderSource extends Source {
  private static final PhoneNumberOfflineGeocoder phoneNumberOfflineGeocoder =
      PhoneNumberOfflineGeocoder.getInstance();
  private static final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();

  @Override
  public boolean canLookup(PhoneNumber inputPhoneNumber) {
    return true;
  }

  @Override
  public CallerIDResult lookup(PhoneNumber inputPhoneNumber, Locale outputLocale) {

    final String address =
        phoneNumberOfflineGeocoder.getDescriptionForNumber(inputPhoneNumber, outputLocale);

    // There is currently no way to tell what resolution the geocoder provided, see
    // https://code.google.com/p/libphonenumber/issues/detail?id=192
    // As a hack, we figure out what the country is, and see if the geocoder simply returned the
    // country name. If it didn't, we assume it returned at least a region level description.
    final AddressResolution addressResolution =
        address.equals(getCountryNameForNumber(inputPhoneNumber, outputLocale))
            ? AddressResolution.COUNTRY
            : AddressResolution.REGION;
    return resultBuilder(inputPhoneNumber, null, address, ListingType.UNKNOWN, addressResolution);
  }

  /**
   * Returns the customary display name in the given language for the given territory the phone
   * number is from.
   */
  private String getCountryNameForNumber(PhoneNumber number, Locale language) {
    String regionCode = phoneNumberUtil.getRegionCodeForNumber(number);
    return getRegionDisplayName(regionCode, language);
  }

  /** Returns the customary display name in the given language for the given region. */
  private String getRegionDisplayName(String regionCode, Locale language) {
    return (regionCode == null
            || regionCode.equals("ZZ")
            || regionCode.equals(PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY))
        ? ""
        : new Locale("", regionCode).getDisplayCountry(language);
  }
}
 private PhoneNumberUtil getPhoneNumberUtil() {
   if (phoneNumberUtil == null) {
     phoneNumberUtil = PhoneNumberUtil.getInstance();
   }
   return phoneNumberUtil;
 }
Example #19
0
public class StringUtil {

  private static final Logger LOGGER = Logger.getLogger(StringUtil.class);
  private static final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
  private static ObjectMapper om;

  public static boolean verifyNumber(String str) {
    if (isNull(str)) {
      return false;
    }
    Pattern pattern = Pattern.compile("1[4-9]32[0-9]{10}");
    Matcher matcher = pattern.matcher(str);
    return matcher.matches();
  }

  public static void main(String[] args) throws Exception {
    ExamResult test = new ExamResult();
    test.setAdmit("hello");
    System.out.println(getObjectMapper().writeValueAsString(test));
    //		System.out.println(verifyNumber("13321001680103"));
    //		System.out.println(verifyNumber("14321001680103"));
    //		System.out.println(verifyNumber("15321001680103"));
  }

  public static boolean isNull(String str) {
    return str == null || str.trim().isEmpty();
  }

  public static boolean isNotNull(String str) {
    return str != null && !str.trim().isEmpty();
  }

  public static String isPhoneNumber(String mobile) {
    String phone = null;
    try {
      LOGGER.debug("test phone number : " + mobile);
      PhoneNumber pn = phoneUtil.parse(mobile, "CN");

      if (phoneUtil.isValidNumber(pn)) {
        phone = phoneUtil.format(pn, PhoneNumberFormat.E164).replace("+86", "");
        LOGGER.debug("phone util parse into cn : " + phone);
      }
    } catch (NumberParseException e) {
      LOGGER.error("parse valid number! ", e);
    }

    if (phone == null) phone = mobile.replace("+", "");

    return phone;
  }

  public static String isMobile(String mobile) {
    String phone = null;
    try {
      PhoneNumber pn = phoneUtil.parse(mobile, "CN");

      if (phoneUtil.isValidNumber(pn)) {
        phone = phoneUtil.format(pn, PhoneNumberFormat.E164).replace("+86", "");
        LOGGER.debug("phone util parse into cn : " + phone);
      }
    } catch (Exception e) {
      LOGGER.error("check mobile error! ", e);
    }

    return phone;
  }

  public static String trim(String str) {
    return str == null ? null : str.trim();
  }

  public static ObjectMapper getObjectMapper() {
    if (om == null) {
      om = new ObjectMapper();
      om.configure(SerializationConfig.Feature.WRITE_NULL_PROPERTIES, false);
      om.getSerializationConfig().withSerializationInclusion(Inclusion.NON_NULL);
    }

    return om;
  }

  public static String formatQuery(String key) {
    return key.replaceAll("%", "");
  }

  public static String getMapStr(Map<String, String> map) throws ServerInternalException {
    String data = null;
    try {
      data = om.writeValueAsString(map);
    } catch (Exception e) {
      throw new ServerInternalException(e, ServerInternalException.OPERATION_FAIL);
    }
    return data;
  }
}
 /**
  * Returns the customary display name in the given language for the given territory the phone
  * number is from.
  */
 private String getCountryNameForNumber(PhoneNumber number, Locale language) {
   String regionCode = phoneNumberUtil.getRegionCodeForNumber(number);
   return getRegionDisplayName(regionCode, language);
 }
 /**
  * As per {@link #lookup(long)}, but receives the number as a PhoneNumber instead of a long.
  *
  * @param number the phone number to look up
  * @return the description corresponding to the prefix that best matches this phone number
  */
 public String lookup(PhoneNumber number) {
   long phonePrefix =
       Long.parseLong(number.getCountryCode() + phoneUtil.getNationalSignificantNumber(number));
   return lookup(phonePrefix);
 }
Example #22
0
  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    log.log(Level.INFO, "RegisterServlet.doPOST() : START RegisterServlet.doPOST()");

    resp.setContentType("text/plain");

    GeatteRegisterRequestInfo reqInfo =
        GeatteRegisterRequestInfo.processRequest(req, resp, getServletContext());
    if (reqInfo == null) {
      log.severe("RegisterServlet.doPOST() : can not load RequestInfo!!");
      return;
    }

    // Because the deviceRegistrationId isn't static, we use a static
    // identifier for the device. (Can be null in older clients)
    String deviceId = reqInfo.getParameter(Config.DEVICE_ID_PARAM);

    if (deviceId == null) {
      resp.setStatus(400);
      resp.getWriter().println(ERROR_STATUS + "(Must specify " + Config.DEVICE_ID_PARAM + ")");
      log.severe(
          "RegisterServlet.doPOST() : Missing device id, " + Config.DEVICE_ID_PARAM + " is null");
      return;
    } else {
      log.log(
          Level.INFO,
          "RegisterServlet.doPOST() : user sent a " + Config.DEVICE_ID_PARAM + " = " + deviceId);
    }

    String phoneNumber = reqInfo.getParameter(Config.DEV_PHONE_NUMBER_PARAM);

    if (phoneNumber == null) {
      resp.setStatus(400);
      resp.getWriter()
          .println(ERROR_STATUS + "(Must specify " + Config.DEV_PHONE_NUMBER_PARAM + ")");
      log.severe(
          "RegisterServlet.doPOST() : Missing phone number, "
              + Config.DEV_PHONE_NUMBER_PARAM
              + " is null");
      return;
    } else {
      log.log(
          Level.INFO,
          "RegisterServlet.doPOST() : user sent a "
              + Config.DEV_PHONE_NUMBER_PARAM
              + " = "
              + phoneNumber);
    }

    String phoneCountryIso = reqInfo.getParameter(Config.DEV_PHONE_COUNTRY_ISO_PARAM);

    if (phoneCountryIso == null) {
      // default is us
      phoneCountryIso = "us";
      log.severe(
          "RegisterServlet.doPOST() : Missing phone country iso, "
              + Config.DEV_PHONE_COUNTRY_ISO_PARAM
              + " is null");
      return;
    } else {
      log.log(
          Level.INFO,
          "RegisterServlet.doPOST() : user sent a "
              + Config.DEV_PHONE_COUNTRY_ISO_PARAM
              + " = "
              + phoneCountryIso);
    }

    PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
    PhoneNumber numberProto = null;
    try {
      numberProto = phoneUtil.parse(phoneNumber, phoneCountryIso);
    } catch (NumberParseException npe) {
      log.log(Level.WARNING, "RegisterServlet.doPOST(): NumberParseException was thrown: ", npe);
    }

    if (numberProto != null && phoneUtil.isValidNumber(numberProto)) {
      phoneNumber = phoneUtil.format(numberProto, PhoneNumberFormat.E164);
    } else {
      log.log(
          Level.WARNING,
          "RegisterServlet.doPOST() : Invalid phone number so use passed-in number, "
              + Config.DEV_PHONE_NUMBER_PARAM
              + " = "
              + phoneNumber
              + ", countryIso = "
              + phoneCountryIso);
    }

    if (reqInfo.deviceRegistrationID == null) {
      resp.setStatus(400);
      resp.getWriter().println(ERROR_STATUS + "(Must specify " + Config.DEV_REG_ID_PARAM + ")");
      log.severe(
          "RegisterServlet.doPOST() : Missing registration id, reqInfo.deviceRegistrationID is null");
      return;
    } else {
      log.log(
          Level.INFO,
          "RegisterServlet.doPOST() : reqInfo.deviceRegistrationID = "
              + reqInfo.deviceRegistrationID);
    }

    String deviceName = reqInfo.getParameter(Config.DEVICE_NAME_PARAM);

    if (deviceName == null) {
      deviceName = "Phone";
      log.log(
          Level.INFO,
          "RegisterServlet.doPOST() : use default "
              + Config.DEVICE_NAME_PARAM
              + " = "
              + deviceName);
    } else {
      log.log(
          Level.INFO,
          "RegisterServlet.doPOST() : user sent a "
              + Config.DEVICE_NAME_PARAM
              + " = "
              + deviceName);
    }
    // TODO: generate the device name by adding a number suffix for multiple
    // devices of same type. Change android app to send model/type.

    String deviceType = reqInfo.getParameter(Config.DEVICE_TYPE_PARAM);

    if (deviceType == null) {
      deviceType = DeviceInfo.TYPE_AC2DM;
      log.log(
          Level.INFO,
          "RegisterServlet.doPOST() : use default "
              + Config.DEVICE_TYPE_PARAM
              + " = "
              + deviceType);
    } else {
      log.log(
          Level.INFO,
          "RegisterServlet.doPOST() : user sent a "
              + Config.DEVICE_TYPE_PARAM
              + " = "
              + deviceType);
    }

    // Context-shared PMF.
    PersistenceManager pm = DBHelper.getPMF(getServletContext()).getPersistenceManager();

    try {
      List<DeviceInfo> registrations = reqInfo.devices;

      if (registrations.size() > MAX_DEVICES) {
        log.log(
            Level.INFO,
            "RegisterServlet.doPOST() : user has too many devices, registrations.size = "
                + registrations.size());
        // we could return an error - but user can't handle it yet.
        // we can't let it grow out of bounds.
        // TODO: we should also define a 'ping' message and
        // expire/remove
        // unused registrations
        DeviceInfo oldest = registrations.get(0);
        if (oldest.getRegistrationTimestamp() == null) {
          log.log(
              Level.INFO,
              "RegisterServlet.doPOST() : user has too many devices, trying to remove old one = "
                  + oldest.getDeviceRegistrationID());
          pm.deletePersistent(oldest);
        } else {
          long oldestTime = oldest.getRegistrationTimestamp().getTime();
          for (int i = 1; i < registrations.size(); i++) {
            if (registrations.get(i).getRegistrationTimestamp().getTime() < oldestTime) {
              oldest = registrations.get(i);
              oldestTime = oldest.getRegistrationTimestamp().getTime();
            }
          }
          log.log(
              Level.INFO,
              "RegisterServlet.doPOST() : user has too many devices, trying to remove old one = "
                  + oldest.getDeviceRegistrationID());
          pm.deletePersistent(oldest);
        }
      }

      // Get device if it already exists, else create
      // String suffix = (deviceId != null ? "#" +
      // Long.toHexString(Math.abs(deviceId.hashCode())) : "");
      // Key key = KeyFactory.createKey(DeviceInfo.class.getSimpleName(),
      // reqInfo.userName + suffix);
      Key key = KeyFactory.createKey(DeviceInfo.class.getSimpleName(), deviceId);

      DeviceInfo device = null;
      try {
        device = pm.getObjectById(DeviceInfo.class, key);
      } catch (JDOObjectNotFoundException e) {
      }
      if (device == null) {
        log.log(
            Level.INFO,
            "RegisterServlet.doPOST() : can not find a DeviceInfo by key = "
                + key
                + ", create a new one");

        // clean devices for same phone number, only one device allowed for one phone
        try {
          List<DeviceInfo> devicesForSameNumber =
              DeviceInfo.getDeviceInfoForNumber(pm, phoneNumber, phoneCountryIso);
          for (DeviceInfo deviceSameNumber : devicesForSameNumber) {
            pm.deletePersistent(deviceSameNumber);
          }
        } catch (JDOObjectNotFoundException e) {
        }

        device = new DeviceInfo(key, reqInfo.deviceRegistrationID);
        device.setType(deviceType);
      } else {
        log.log(
            Level.INFO,
            "RegisterServlet.doPOST() : find a DeviceInfo by key = "
                + key
                + ", update deviceRegistrationID to "
                + reqInfo.deviceRegistrationID);

        // update registration id
        device.setDeviceRegistrationID(reqInfo.deviceRegistrationID);
        device.setRegistrationTimestamp(new Date());
      }

      device.setPhoneNumber(phoneNumber); // update phoneNumber
      device.setCountryCode(phoneCountryIso); // update country code
      device.setUserEmail(reqInfo.getUserEmail()); // update user email
      device.setDeviceName(deviceName); // update display name
      // TODO: only need to write if something changed, for chrome nothing
      // changes, we just create a new channel
      pm.makePersistent(device);

      log.log(
          Level.INFO,
          "RegisterServlet.doPOST() : Registered device userEmail = "
              + reqInfo.getUserEmail()
              + ", deviceType = "
              + deviceType
              + ", deviceRegistrationID = "
              + reqInfo.deviceRegistrationID
              + ", key = "
              + key);

      // if type is IOS, register to Urban
      if (device.getType().equalsIgnoreCase(DeviceInfo.TYPE_IOS)) {
        doRegisterIOSToUrban(device);
        resp.getWriter().println(OK_STATUS);
      } else if (device.getType().equalsIgnoreCase(DeviceInfo.TYPE_ANDROID)
          || device.getType().equalsIgnoreCase(DeviceInfo.TYPE_AC2DM)) {
        resp.getWriter().println(OK_STATUS);
      } else {
        resp.getWriter().println(ERROR_STATUS + "(Wrong " + Config.DEVICE_TYPE_PARAM + ")");
      }

      log.log(Level.INFO, "RegisterServlet.doPOST() : END RegisterServlet.doPOST()");
    } catch (Exception e) {
      resp.setStatus(500);
      resp.getWriter().println(ERROR_STATUS + " (Error registering device)");
      log.log(Level.WARNING, "RegisterServlet.doPOST() : Error registering device.", e);
    } finally {
      pm.close();
    }
  }
/**
 * A utility that maps phone number prefixes to a description string, which may be, for example, the
 * geographical area the prefix covers.
 *
 * @author Shaopeng Jia
 */
public class PhonePrefixMap implements Externalizable {
  private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
  private static final Logger logger = Logger.getLogger(PhonePrefixMap.class.getName());

  private PhonePrefixMapStorageStrategy phonePrefixMapStorage;

  // @VisibleForTesting
  PhonePrefixMapStorageStrategy getPhonePrefixMapStorage() {
    return phonePrefixMapStorage;
  }

  /**
   * Creates an empty {@link PhonePrefixMap}. The default constructor is necessary for implementing
   * {@link Externalizable}. The empty map could later be populated by {@link
   * #readPhonePrefixMap(java.util.SortedMap)} or {@link #readExternal(java.io.ObjectInput)}.
   */
  public PhonePrefixMap() {}

  /**
   * Gets the size of the provided phone prefix map storage. The map storage passed-in will be
   * filled as a result.
   */
  private static int getSizeOfPhonePrefixMapStorage(
      PhonePrefixMapStorageStrategy mapStorage, SortedMap<Integer, String> phonePrefixMap)
      throws IOException {
    mapStorage.readFromSortedMap(phonePrefixMap);
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
    mapStorage.writeExternal(objectOutputStream);
    objectOutputStream.flush();
    int sizeOfStorage = byteArrayOutputStream.size();
    objectOutputStream.close();
    return sizeOfStorage;
  }

  private PhonePrefixMapStorageStrategy createDefaultMapStorage() {
    return new DefaultMapStorage();
  }

  private PhonePrefixMapStorageStrategy createFlyweightMapStorage() {
    return new FlyweightMapStorage();
  }

  /**
   * Gets the smaller phone prefix map storage strategy according to the provided phone prefix map.
   * It actually uses (outputs the data to a stream) both strategies and retains the best one which
   * make this method quite expensive.
   */
  // @VisibleForTesting
  PhonePrefixMapStorageStrategy getSmallerMapStorage(SortedMap<Integer, String> phonePrefixMap) {
    try {
      PhonePrefixMapStorageStrategy flyweightMapStorage = createFlyweightMapStorage();
      int sizeOfFlyweightMapStorage =
          getSizeOfPhonePrefixMapStorage(flyweightMapStorage, phonePrefixMap);

      PhonePrefixMapStorageStrategy defaultMapStorage = createDefaultMapStorage();
      int sizeOfDefaultMapStorage =
          getSizeOfPhonePrefixMapStorage(defaultMapStorage, phonePrefixMap);

      return sizeOfFlyweightMapStorage < sizeOfDefaultMapStorage
          ? flyweightMapStorage
          : defaultMapStorage;
    } catch (IOException e) {
      logger.severe(e.getMessage());
      return createFlyweightMapStorage();
    }
  }

  /**
   * Creates an {@link PhonePrefixMap} initialized with {@code sortedPhonePrefixMap}. Note that the
   * underlying implementation of this method is expensive thus should not be called by
   * time-critical applications.
   *
   * @param sortedPhonePrefixMap a map from phone number prefixes to descriptions of those prefixes
   *     sorted in ascending order of the phone number prefixes as integers.
   */
  public void readPhonePrefixMap(SortedMap<Integer, String> sortedPhonePrefixMap) {
    phonePrefixMapStorage = getSmallerMapStorage(sortedPhonePrefixMap);
  }

  /** Supports Java Serialization. */
  public void readExternal(ObjectInput objectInput) throws IOException {
    // Read the phone prefix map storage strategy flag.
    boolean useFlyweightMapStorage = objectInput.readBoolean();
    if (useFlyweightMapStorage) {
      phonePrefixMapStorage = new FlyweightMapStorage();
    } else {
      phonePrefixMapStorage = new DefaultMapStorage();
    }
    phonePrefixMapStorage.readExternal(objectInput);
  }

  /** Supports Java Serialization. */
  public void writeExternal(ObjectOutput objectOutput) throws IOException {
    objectOutput.writeBoolean(phonePrefixMapStorage instanceof FlyweightMapStorage);
    phonePrefixMapStorage.writeExternal(objectOutput);
  }

  /**
   * Returns the description of the {@code number}. This method distinguishes the case of an invalid
   * prefix and a prefix for which the name is not available in the current language. If the
   * description is not available in the current language an empty string is returned. If no
   * description was found for the provided number, null is returned.
   *
   * @param number the phone number to look up
   * @return the description of the number
   */
  String lookup(long number) {
    int numOfEntries = phonePrefixMapStorage.getNumOfEntries();
    if (numOfEntries == 0) {
      return null;
    }
    long phonePrefix = number;
    int currentIndex = numOfEntries - 1;
    SortedSet<Integer> currentSetOfLengths = phonePrefixMapStorage.getPossibleLengths();
    while (currentSetOfLengths.size() > 0) {
      Integer possibleLength = currentSetOfLengths.last();
      String phonePrefixStr = String.valueOf(phonePrefix);
      if (phonePrefixStr.length() > possibleLength) {
        phonePrefix = Long.parseLong(phonePrefixStr.substring(0, possibleLength));
      }
      currentIndex = binarySearch(0, currentIndex, phonePrefix);
      if (currentIndex < 0) {
        return null;
      }
      int currentPrefix = phonePrefixMapStorage.getPrefix(currentIndex);
      if (phonePrefix == currentPrefix) {
        return phonePrefixMapStorage.getDescription(currentIndex);
      }
      currentSetOfLengths = currentSetOfLengths.headSet(possibleLength);
    }
    return null;
  }

  /**
   * As per {@link #lookup(long)}, but receives the number as a PhoneNumber instead of a long.
   *
   * @param number the phone number to look up
   * @return the description corresponding to the prefix that best matches this phone number
   */
  public String lookup(PhoneNumber number) {
    long phonePrefix =
        Long.parseLong(number.getCountryCode() + phoneUtil.getNationalSignificantNumber(number));
    return lookup(phonePrefix);
  }

  /**
   * Does a binary search for {@code value} in the provided array from {@code start} to {@code end}
   * (inclusive). Returns the position if {@code value} is found; otherwise, returns the position
   * which has the largest value that is less than {@code value}. This means if {@code value} is the
   * smallest, -1 will be returned.
   */
  private int binarySearch(int start, int end, long value) {
    int current = 0;
    while (start <= end) {
      current = (start + end) >>> 1;
      int currentValue = phonePrefixMapStorage.getPrefix(current);
      if (currentValue == value) {
        return current;
      } else if (currentValue > value) {
        current--;
        end = current;
      } else {
        start = current + 1;
      }
    }
    return current;
  }

  /** Dumps the mappings contained in the phone prefix map. */
  @Override
  public String toString() {
    return phonePrefixMapStorage.toString();
  }
}
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.number_validation);

    mAccountManager = AccountManager.get(this);
    mHandler = new Handler();

    lbm = LocalBroadcastManager.getInstance(getApplicationContext());

    final Intent intent = getIntent();
    mFromInternal = intent.getBooleanExtra(PARAM_FROM_INTERNAL, false);

    mNameText = (EditText) findViewById(R.id.name);
    mCountryCode = (Spinner) findViewById(R.id.phone_cc);
    mPhone = (EditText) findViewById(R.id.phone_number);
    mValidateButton = (Button) findViewById(R.id.button_validate);
    mInsertCode = (Button) findViewById(R.id.button_validation_code);

    // populate country codes
    final CountryCodesAdapter ccList =
        new CountryCodesAdapter(this, R.layout.country_item, R.layout.country_dropdown_item);
    PhoneNumberUtil util = PhoneNumberUtil.getInstance();
    Set<String> ccSet = getSupportedRegions(util);
    for (String cc : ccSet) ccList.add(cc);

    ccList.sort(
        new Comparator<CountryCodesAdapter.CountryCode>() {
          public int compare(
              CountryCodesAdapter.CountryCode lhs, CountryCodesAdapter.CountryCode rhs) {
            return lhs.regionName.compareTo(rhs.regionName);
          }
        });
    mCountryCode.setAdapter(ccList);
    mCountryCode.setOnItemSelectedListener(
        new AdapterView.OnItemSelectedListener() {
          public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            ccList.setSelected(position);
          }

          public void onNothingSelected(AdapterView<?> parent) {
            // TODO Auto-generated method stub
          }
        });

    // FIXME this doesn't consider creation because of configuration change
    PhoneNumber myNum = NumberValidator.getMyNumber(this);
    if (myNum != null) {
      mPhone.setText(String.valueOf(myNum.getNationalNumber()));
      Log.d(TAG, "selecting country " + util.getRegionCodeForNumber(myNum));
      CountryCode cc = new CountryCode();
      cc.regionCode = util.getRegionCodeForNumber(myNum);
      cc.countryCode = myNum.getCountryCode();
      mCountryCode.setSelection(ccList.getPositionForId(cc));
    } else {
      final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
      final String regionCode = tm.getSimCountryIso().toUpperCase(Locale.US);
      CountryCode cc = new CountryCode();
      cc.regionCode = regionCode;
      cc.countryCode = util.getCountryCodeForRegion(regionCode);
      mCountryCode.setSelection(ccList.getPositionForId(cc));
    }

    // configuration change??
    RetainData data = (RetainData) getLastCustomNonConfigurationInstance();
    if (data != null) {
      synchronized (this) {
        // sync starter was queued, we can exit
        if (data.syncing) {
          delayedSync();
        }

        mValidator = data.validator;
        if (mValidator != null) mValidator.setListener(this);
      }
      if (data.progressMessage != null) {
        setProgressMessage(data.progressMessage, true);
      }
    }
  }
  public static ArrayList<PhoneBookContact> loadPhoneBook(Context context, String isoCountry) {
    if (DISABLE_PHONE_BOOK) {
      return new ArrayList<PhoneBookContact>();
    }

    Log.d(TAG, "Loading phone book");
    long start = SystemClock.uptimeMillis();

    HashSet<Long> addedPhones = new HashSet<Long>();
    HashSet<String> addedEmails = new HashSet<String>();
    ArrayList<PhoneBookContact> records = new ArrayList<PhoneBookContact>();
    HashMap<Long, PhoneBookContact> recordsMap = new HashMap<Long, PhoneBookContact>();

    ContentResolver cr = context.getContentResolver();
    if (cr == null) {
      return new ArrayList<PhoneBookContact>();
    }

    // Loading records
    // TODO: Better logic for duplicate phones
    // Check have permission for this
    if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_CONTACTS)
            != PackageManager.PERMISSION_GRANTED
        && ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS)
            != PackageManager.PERMISSION_GRANTED) {
      Log.d("Permissions", "contacts - no permission :c");
      return new ArrayList<PhoneBookContact>();
    }
    Cursor cur =
        cr.query(
            ContactsContract.Contacts.CONTENT_URI,
            new String[] {ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME},
            null,
            null,
            ContactsContract.Contacts.SORT_KEY_PRIMARY);
    if (cur == null) {
      return new ArrayList<PhoneBookContact>();
    }
    int idIndex = cur.getColumnIndex(ContactsContract.Contacts._ID);
    int nameIndex = cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);

    int index = 0;
    while (cur.moveToNext()) {
      if (index++ == READ_ITEM_DELAY_BATCH) {
        if (READ_ITEM_DELAY > 0) {
          try {
            Thread.sleep(READ_ITEM_DELAY);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }

      long id = cur.getLong(idIndex);
      String name = cur.getString(nameIndex);
      if (name == null || name.trim().length() == 0) continue;

      PhoneBookContact record =
          new PhoneBookContact(
              id, name.trim(), new ArrayList<PhoneBookPhone>(), new ArrayList<PhoneBookEmail>());
      records.add(record);
      recordsMap.put(id, record);
    }
    cur.close();
    cur = null;

    // Loading phones
    cur =
        cr.query(
            ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            new String[] {
              ContactsContract.CommonDataKinds.Phone._ID,
              ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
              ContactsContract.CommonDataKinds.Phone.NUMBER
            },
            null,
            null,
            ContactsContract.CommonDataKinds.Phone._ID + " desc");
    if (cur == null) {
      return new ArrayList<PhoneBookContact>();
    }

    final int idContactIndex =
        cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID);
    final int idPhoneIndex = cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID);
    final int idNumberIndex = cur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);

    while (cur.moveToNext()) {
      if (index++ == READ_ITEM_DELAY_BATCH) {
        if (READ_ITEM_DELAY > 0) {
          try {
            Thread.sleep(READ_ITEM_DELAY);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }

      long contactId = cur.getLong(idContactIndex);
      long phoneId = cur.getLong(idPhoneIndex);
      String rawPhone = cur.getString(idNumberIndex);
      PhoneBookContact record = recordsMap.get(contactId);
      if (record == null) {
        continue;
      }

      try {
        final Phonenumber.PhoneNumber phonenumber = phoneUtil.parse(rawPhone, isoCountry);
        rawPhone = phonenumber.getCountryCode() + "" + phonenumber.getNationalNumber();
      } catch (final NumberParseException e) {
        rawPhone = rawPhone.replaceAll("[^\\d]", "");
      }
      long phone = -1;
      try {
        phone = Long.parseLong(rawPhone);
      } catch (Exception e) {
        // Logger.d(TAG, "Can't parse number", e);
        continue;
      }

      if (addedPhones.contains(phone)) {
        continue;
      }
      addedPhones.add(phone);

      record.getPhones().add(new PhoneBookPhone(phoneId, phone));
    }
    cur.close();
    cur = null;

    // Loading emails
    cur =
        cr.query(
            ContactsContract.CommonDataKinds.Email.CONTENT_URI,
            new String[] {
              ContactsContract.CommonDataKinds.Email._ID,
              ContactsContract.CommonDataKinds.Email.CONTACT_ID,
              ContactsContract.CommonDataKinds.Email.ADDRESS
            },
            null,
            null,
            ContactsContract.CommonDataKinds.Email._ID + " desc");

    if (cur == null) {
      return new ArrayList<PhoneBookContact>();
    }

    final int idEmailContactIndex =
        cur.getColumnIndex(ContactsContract.CommonDataKinds.Email.CONTACT_ID);
    final int idEmailIdIndex = cur.getColumnIndex(ContactsContract.CommonDataKinds.Email._ID);
    final int idEmailIndex = cur.getColumnIndex(ContactsContract.CommonDataKinds.Email.ADDRESS);

    while (cur.moveToNext()) {
      if (index++ == READ_ITEM_DELAY_BATCH) {
        if (READ_ITEM_DELAY > 0) {
          try {
            Thread.sleep(READ_ITEM_DELAY);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }

      long contactId = cur.getLong(idEmailContactIndex);
      long emailId = cur.getLong(idEmailIdIndex);
      String rawEmail = cur.getString(idEmailIndex);
      PhoneBookContact record = recordsMap.get(contactId);
      if (record == null) {
        continue;
      }

      if (rawEmail == null) {
        continue;
      }
      rawEmail = rawEmail.toLowerCase();

      if (addedEmails.contains(rawEmail)) {
        continue;
      }
      addedEmails.add(rawEmail);

      record.getEmails().add(new PhoneBookEmail(emailId, rawEmail));
    }
    cur.close();

    // Filtering records without contacts
    ArrayList<PhoneBookContact> res = new ArrayList<PhoneBookContact>();
    for (PhoneBookContact rec : records) {
      if (rec.getPhones().size() > 0 || rec.getEmails().size() > 0) {
        res.add(rec);
      }
    }
    Log.d(
        TAG,
        "Phone book loaded in "
            + (SystemClock.uptimeMillis() - start)
            + " ms in "
            + (index)
            + " iterations");
    return res;
  }