1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package com.hustbill;

import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.stream.StreamSupport.stream;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;

import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.twilio.sdk.LookupsClient;
import com.twilio.sdk.TwilioRestException;

public class ParallelPhoneValidator {
 static double sink;
 static Set<PhoneNumber> result = new HashSet<PhoneNumber>();

 // Find your Account Sid and Token at twilio.com/user/account
 public static final String ACCOUNT_SID = "ACbdc579bf50d3995b262a44f24d6f1491";
 public static final String AUTH_TOKEN = "c330fec63941a84f36729bc287c1a0ff";

 public static void main(String[] args) throws IOException {
  final Path inputPath = Paths.get("src/main/resources/data.txt");
  for (int i = 1; i < 3; i++) {
   System.out.printf("Start Sequentially processing %d round stream \n", i);
   measureProcessing(Files.lines(inputPath));
   
   System.out.printf("Start Parallel processing %d round stream \n", i);
   measureProcessing(withBatchSize(Files.lines(inputPath), 10));
   }

  System.out.println("Validated Cell Numbers");
  for (PhoneNumber phoneNum : result) {
   long nationalNumber = phoneNum.getNationalNumber();
   System.out.println("   " + nationalNumber );
  }
 }

 private static void measureProcessing(Stream<String> input) throws IOException {
  final long start = System.nanoTime();

  try (Stream<String> lines = input) {
   final long totalTime = lines.parallel().mapToLong(ParallelPhoneValidator::processLine).sum();

   final double cpuTime = totalTime, realTime = System.nanoTime() - start;
   final int cores = Runtime.getRuntime().availableProcessors();
   System.out.println(" Cell Phone Num: " + result.size());
   System.out.println("          Cores: " + cores);
   System.out.format("       CPU time: %.2f s\n", cpuTime / SECONDS.toNanos(1));
   System.out.format("      Real time: %.2f s\n", realTime / SECONDS.toNanos(1));
   System.out.format("CPU utilization: %.2f%%\n\n", 100.0 * cpuTime / realTime / cores);

  }
 }

 /*
  * Determine if the phone number is a valid phone number using Google's
  * libphonenumber
  * Google's common Java, C++ and JavaScript library for parsing, formatting,
  * and validating international phone numbers.
  */
 private static long processLine(String usaNumberStr) {
  final long localStart = System.nanoTime();

  PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
  LRUCache cache = new LRUCache(1000);

  try {
   PhoneNumber usaNumberProto = phoneUtil.parse(usaNumberStr, "US");
   boolean isValid = phoneUtil.isValidNumber(usaNumberProto);

   if (isValid) {
    long key = usaNumberProto.getNationalNumber();
    if (cache.get(key) != -1) {
     if (cache.get(key) == 1) { // 1 - MOBILE
      result.add(usaNumberProto);
     }
    } else {
     if (twilioLookup(usaNumberProto) == "MOBILE") {
      result.add(usaNumberProto);
      cache.set(key, 1);
     } else {
      cache.set(key, 0); // 0 - LANDLINE
     }
    }
   }
  } catch (Exception e) {
   System.err.println("NumberParseException was thrown: " + e.toString());
  }

  return System.nanoTime() - localStart;
 }

 public static <T> Stream<T> withBatchSize(Stream<T> in, int batchSize) {
  return stream(new FixedBatchSpliterator<>(in.spliterator(), batchSize), true);
 }

 /*
  * Get the type of a phone : Landline or Mobile by Twilio Lookup API.
  * Twilio Lookup is a simple REST API with a ton of utility. Twilio
  * https://www.twilio.com/lookup determine whether a phone is a landline or
  * can receive text messages, and even discover information about the
  * carrier associated with that phone number.
  */
 public static String twilioLookup(PhoneNumber number) throws TwilioRestException {
  String strNum = String.valueOf(number.getNationalNumber());

  LookupsClient client = new LookupsClient(ACCOUNT_SID, AUTH_TOKEN);
  com.twilio.sdk.resource.instance.lookups.PhoneNumber phoneNumber = client.getPhoneNumber(strNum, true);

  return phoneNumber.getType().toString();
 }

}