package crmdna.common;
import com.google.appengine.api.users.User;
import crmdna.common.api.APIException;
import crmdna.common.api.APIResponse.Status;
import crmdna.common.api.RequestInfo;
import crmdna.common.config.ConfigCRMDNA;
import crmdna.email.EmailProp;
import crmdna.email.GAEEmail;
import crmdna.refdata.CountryProp;
import crmdna.refdata.RefData;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.*;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static crmdna.common.AssertUtils.*;
public class Utils {
private static final String[] HEX_LOOKUP_TABLE = new String[]{"00", "01", "02", "03", "04",
"05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11", "12", "13",
"14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22",
"23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31",
"32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40",
"41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e",
"5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d",
"6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c",
"7d", "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b",
"8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a",
"9b", "9c", "9d", "9e", "9f", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9",
"aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8",
"b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7",
"c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6",
"d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5",
"e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4",
"f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"};
public enum SingleChar {
a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
}
public static Set<String> getQSTags_old(String... fields) {
// creates all combinations of 3 consecutive character as a set
// eg: if invoked with getQSTags("sathya", "thilakan") the set
// will be populated as: sat, ath, thy, hya, thi, hil, ila, aka, kan
Set<String> set = new TreeSet<>();
for (int i = 0; i < fields.length; i++) {
if (fields[i] == null)
continue;
fields[i] = fields[i].toLowerCase();
if (fields[i].length() < 3)
continue;
for (int beginIndex = 0; beginIndex < fields[i].length() - 2; beginIndex++) {
set.add(fields[i].substring(beginIndex, beginIndex + 3));
}
}
return set;
}
public static String toHexStr(byte[] bytes) {
if (bytes == null) {
return null;
}
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
sb.append(HEX_LOOKUP_TABLE[((int) bytes[i]) & 0xff]);
}
return sb.toString();
}
public static byte[] toByteArray(String hexStr) {
if (hexStr == null) {
return null;
}
if ((hexStr.length() % 2) != 0) {
throw new APIException().status(Status.ERROR_INVALID_INPUT).message(
"Expected length of the input to be even.");
}
hexStr = hexStr.toLowerCase();
int numBytes = hexStr.length() / 2;
byte[] bytes = new byte[numBytes];
for (int i = 0, j = 0; i < numBytes; i++, j += 2) {
int c1 = hexStr.charAt(j) - '0';
if (c1 > 9) {
c1 = c1 + '0' - 'a' + 10;
}
int c2 = hexStr.charAt(j + 1) - '0';
if (c2 > 9) {
c2 = c2 + '0' - 'a' + 10;
}
bytes[i] = (byte) (((c1 << 4) + c2) & 0xff);
}
return bytes;
}
public static Set<String> getQSTags(String... fields) {
// creates all combinations of 3 consecutive character as a set
// eg: if invoked with getQSTags("sathya", "thilakan") the set
// will be populated as: sat, ath, thy, hya, thi, hil, ila, aka, kan
Set<String> set = new TreeSet<>();
// if any of the field has a space then split it.
List<String> fieldsAfterSplitting = new ArrayList<>();
for (int i = 0; i < fields.length; i++) {
if (fields[i] == null)
continue;
String[] split = fields[i].split("\\s+");
ensureNotNull(split, "array after splitting by \\s+ is null");
for (int j = 0; j < split.length; j++) {
fieldsAfterSplitting.add(split[j]);
}
}
for (String field : fieldsAfterSplitting) {
if (fields == null)
continue;
field = field.toLowerCase();
if (field.length() < 3)
continue;
for (int beginIndex = 0; beginIndex < field.length() - 2; beginIndex++) {
set.add(field.substring(beginIndex, beginIndex + 3));
}
}
return set;
}
public static boolean closeEnough(String s1, String s2) {
if ((s1 == null) || (s2 == null))
return false;
s1 = s1.toLowerCase().replaceAll(" ", "");
s2 = s2.toLowerCase().replaceAll(" ", "");
// if less than or equal to 3 char, entire string should match
if (s1.length() <= 3)
return s1.equals(s2);
// if first 3 chars match return true
if (s1.substring(0, 3).equals(s2.substring(0, 3)))
return true;
Set<String> s1QSTags = getQSTags(s1);
Set<String> s2QSTags = getQSTags(s2);
s1QSTags.retainAll(s2QSTags);
return s1QSTags.size() > Math.min(s1.length(), s1.length()) / 3;
}
public static boolean isValidEmailAddress(String email) {
if (null == email)
return false;
boolean stricterFilter = true;
String stricterFilterString = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
String laxString = ".+@.+\\.[A-Za-z]{2}[A-Za-z]*";
String emailRegex = stricterFilter ? stricterFilterString : laxString;
java.util.regex.Pattern p = java.util.regex.Pattern.compile(emailRegex);
java.util.regex.Matcher m = p.matcher(email);
return m.matches();
}
public static boolean isPresentInListCaseInsensitive(List<String> list, String s) {
if ((null == list) || (null == s))
return false;
for (String element : list) {
if (element.equalsIgnoreCase(s))
return true;
}
return false;
}
public static String getLoginEmail(User user) {
if (null == user)
return null;
return user.getEmail();
}
public static void throwIncorrectSpecException(String message) {
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(message);
}
public static void throwNotFoundException(String message) {
throw new APIException().status(Status.ERROR_RESOURCE_NOT_FOUND).message(message);
}
public static void throwAlreadyExistsException(String message) {
throw new APIException().status(Status.ERROR_RESOURCE_ALREADY_EXISTS).message(message);
}
public static void ensureValidPhoneNumber(String phoneNumber) {
// TODO: remove code duplication in isValidPhoneNumber function
final String phoneNumberRegex =
"\\+(9[976]\\d|8[987530]\\d|6[987]\\d|5[90]\\d|42\\d|3[875]\\d|"
+ "2[98654321]\\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|"
+ "4[987654310]|3[9643210]|2[70]|7|1)\\d{1,14}$";
if ((phoneNumber == null) || (phoneNumber.equals("")))
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(
"Phone number cannot be null or empty");
if (phoneNumber.charAt(0) != '+')
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(
"First character of phone number should be +");
if (!phoneNumber.matches(phoneNumberRegex))
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(
"Phone number [" + phoneNumber + "] is invalid");
}
public static boolean isValidPhoneNumber(String phoneNumber) {
// Make this function also take in country as input and do a stricter
// validation
final String phoneNumberRegex =
"\\+(9[976]\\d|8[987530]\\d|6[987]\\d|5[90]\\d|42\\d|3[875]\\d|"
+ "2[98654321]\\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|"
+ "4[987654310]|3[9643210]|2[70]|7|1)\\d{1,14}$";
if ((phoneNumber == null) || phoneNumber.equals(""))
return false;
if (phoneNumber.charAt(0) != '+')
return false;
if (!phoneNumber.matches(phoneNumberRegex))
return false;
return true;
}
public static String getPhoneNoErrMsgIfAnyElseNull(String phoneNumber, String country,
PhoneNoType phoneNoType) {
// Make this function also take in country as input and do a stricter
// validation
CountryProp countryProp = RefData.getCountryProp(country);
if (countryProp == null)
return "["
+ country
+ "] is not a valid country or not yet added to IshaCRM. To add a country to IshaCRM please email ["
+ "sathya.t@ishafoundation.org]";
if (phoneNoType == PhoneNoType.LANDLINE) {
if (!phoneNumber.matches(countryProp.landlineRegex))
return countryProp.messageIfError;
} else if (phoneNoType == PhoneNoType.MOBILE) {
if (!phoneNumber.matches(countryProp.mobileRegex))
return countryProp.messageIfError;
} else {
// should never come here
throw new APIException().status(Status.ERROR_INTERNAL).message(
"Internal error when validating phone no");
}
return null;
}
public static String getPhoneNoErrMsgIfAnyElseNull(String phoneNo, String country) {
// Make this function also take in country as input and do a stricter
// validation
CountryProp countryProp = RefData.getCountryProp(country);
if (countryProp == null)
return "["
+ country
+ "] is not a valid country or not yet added to IshaCRM. To add a country to IshaCRM please email ["
+ "sathya.t@ishafoundation.org]";
if (!phoneNo.matches(countryProp.landlineRegex) && !phoneNo.matches(countryProp.mobileRegex)) {
return countryProp.messageIfError;
}
return null;
}
public static void ensureValidEmail(String email) {
if ((email == null) || (email.equals("")))
throw new APIException("Email cannot be null or empty")
.status(Status.ERROR_RESOURCE_INCORRECT);
boolean valid = Utils.isValidEmailAddress(email);
if (valid == false)
throw new APIException("Email [" + email + "] is invalid")
.status(Status.ERROR_RESOURCE_INCORRECT);
}
public static void ensureValidUrl(String url) {
try {
new URL(url);
} catch (MalformedURLException e) {
Utils.throwIncorrectSpecException("URL [" + url + "] is invalid");
}
}
public static long safeParseAsLong(String s) {
try {
ensureNotNull(s, "s is null");
long l = Long.parseLong(s);
return l;
} catch (NumberFormatException e) {
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(
"Cannot parse [" + s + "] as long");
}
}
public static boolean canParseAsLong(String s) {
try {
safeParseAsLong(s);
return true;
} catch (Exception ex) {
return false;
}
}
public static int safeParseAsInt(String s) {
try {
int i = Integer.parseInt(s);
return i;
} catch (NumberFormatException e) {
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(
"Cannot parse [" + s + "] as integer");
}
}
public static double safeParseAsDouble(String s) {
try {
double d = Double.parseDouble(s);
return d;
} catch (NumberFormatException e) {
throw new APIException().status(Status.ERROR_RESOURCE_INCORRECT).message(
"Cannot parse [" + s + "] as double");
}
}
@SafeVarargs
public static <T> List<T> getList(T... elements) {
List<T> list = new ArrayList<>();
for (T element : elements) {
list.add(element);
}
return list;
}
@SafeVarargs
public static <T> Set<T> getSet(T... elements) {
Set<T> set = new HashSet<>();
for (T element : elements) {
set.add(element);
}
return set;
}
public static String getUrl(String baseUrl, Map<String, Object> queryParams) {
Utils.ensureValidUrl(baseUrl);
if (queryParams == null)
return baseUrl;
// sort query params by key
Map<String, Object> treeMap = new TreeMap<>();
treeMap.putAll(queryParams);
queryParams = treeMap;
StringBuilder builder = new StringBuilder(baseUrl);
if (!baseUrl.contains("?"))
builder.append("?");
else
builder.append("&");
for (String key : queryParams.keySet()) {
try {
final String ENCODING_SCHEME = "UTF-8";
String encodedKey = URLEncoder.encode(key, ENCODING_SCHEME);
String encodedValue = URLEncoder.encode(queryParams.get(key).toString(), ENCODING_SCHEME);
if (encodedValue.length() > 250)
encodedValue = encodedValue.substring(0, 250);
builder.append(encodedKey + "=" + encodedValue + "&");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException("Unsupported Encoding Exception. Message: " + e.getMessage());
}
}
String url = builder.toString();
// space should be encoded as %20, java encoder encodes it as a +
url = url.replaceAll(Pattern.quote("+"), "%20");
// should be valid - but just in case
Utils.ensureValidUrl(url);
return url;
}
public static void ensureNonNegative(double n) {
if (n < 0)
throwIncorrectSpecException("Specified number [" + n + "] is negative");
}
public static int getNumDays(Date former, Date later) {
final int MILLI_SECONDS_IN_A_DAY = 3600 * 24 * 1000;
int numDays = (int) (former.getTime() - later.getTime()) / MILLI_SECONDS_IN_A_DAY;
return numDays;
}
public static String getFullName(String firstName, String lastName) {
if ((firstName == null) && (lastName == null))
return null;
if (firstName == null)
return lastName;
if (lastName == null)
return firstName;
return firstName + " " + lastName;
}
public static String getAbbrev(String fullName) {
String[] list = fullName.split("[ ,:]");
String abbrev = new String();
for (String s : list) {
if (! s.isEmpty())
abbrev += s.charAt(0);
}
return abbrev.toUpperCase();
}
public static String asCurrencyString(double d) {
DecimalFormat df = new DecimalFormat("#.00");
return df.format(d);
}
public static String urlEncode(String url) {
try {
url = URLEncoder.encode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new APIException().status(Status.ERROR_OPERATION_NOT_ALLOWED).message(
"Exception thrown by URLEncoder.encode for url [" + url + "]");
}
url.replaceAll(Pattern.quote("+"), "%20");
return url;
}
public static void ensureNotNullOrEmpty(String value, String errMessage) {
if ((value == null) || value.equals(""))
Utils.throwIncorrectSpecException(errMessage);
}
public static void ensureNonZero(long value, String errMessage) {
if (value == 0)
Utils.throwIncorrectSpecException(errMessage);
}
public static String csvEncode(String s) {
if (s == null)
return "";
s = s.replaceAll(Pattern.quote("\""), "");
if (s.contains(",") || s.contains("\r\n"))
return "\"" + s + "\"";
return s;
}
public static String stackTraceToString_old(Throwable e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
public static String stackTraceToString(Throwable e) {
if (e == null)
return null;
StringBuilder builder = new StringBuilder();
builder.append(e.getMessage() + "<br>");
StackTraceElement[] stElements = e.getStackTrace();
for (int i = 0; i < stElements.length; i++) {
builder.append(stElements[i].toString());
builder.append("<br>");
}
return builder.toString();
}
// TODO: move this to incidents package later
public static void sendAlertEmailToDevTeam(String client, Exception ex, HttpServletRequest req,
String login) {
try {
ensureNotNull(ex, "Exception is null");
// to address
EmailProp emailProp = new EmailProp();
emailProp.toEmailAddresses = ConfigCRMDNA.get().toProp().devTeamEmails;
if (emailProp.toEmailAddresses.size() == 0)
emailProp.toEmailAddresses.add(crmdna.user.User.SUPER_USER);
if (client == null)
client = "Not Available";
// subject
emailProp.subject = "Unhandled exception for [" + client + "]: " + ex.getMessage();
// body
StringBuilder builder = new StringBuilder();
builder.append("<br><i>Logged in user:</i> " + login + "<br><br>");
builder.append("<i>Timestamp:</i> " + new Date() + "<br><br>");
if (req != null) {
builder.append("<i>Request:</i> " + req.getRequestURI() + "<br><br>");
@SuppressWarnings("unchecked")
Enumeration<String> parameterNames = req.getParameterNames();
if (parameterNames.hasMoreElements()) {
builder.append("<i>Query parameters: </i><br>");
while (parameterNames.hasMoreElements()) {
String key = (String) parameterNames.nextElement();
String value = req.getParameter(key);
builder.append(key + ": " + value + "<br>");
}
}
builder.append("<br>");
@SuppressWarnings("unchecked")
Enumeration<String> headerNames = req.getParameterNames();
if (headerNames.hasMoreElements()) {
builder.append("<i>Headers: </i><br>");
while (headerNames.hasMoreElements()) {
String key = (String) parameterNames.nextElement();
String value = req.getParameter(key);
builder.append(key + ": " + value + "<br>");
}
}
}
builder.append("<br>");
builder.append("<i>Exception message:</i> " + ex.getMessage());
builder.append("<br><br>");
builder.append("<i>Stack trace:</i><br>");
builder.append(stackTraceToString(ex));
emailProp.bodyHtml = builder.toString();
GAEEmail.send(emailProp);
} catch (Exception exception) {
// This is usually called in response to a unhandled exception.
// just log the exception and swallow it
Logger logger = Logger.getLogger(Utils.class.getName());
logger.severe(stackTraceToString(exception));
}
}
// TODO: move this to incidents package later
public static void sendAlertEmailToDevTeam(Exception ex, RequestInfo requestInfo) {
try {
if (ex == null)
return;
// requestInfo can be null
// to address
EmailProp emailProp = new EmailProp();
emailProp.toEmailAddresses = ConfigCRMDNA.get().toProp().devTeamEmails;
if (emailProp.toEmailAddresses.size() == 0)
emailProp.toEmailAddresses.add(crmdna.user.User.SUPER_USER);
String client = "Not Available";
if ((requestInfo != null) && (requestInfo.getClient() != null))
client = requestInfo.getClient();
// subject
emailProp.subject = "Unhandled exception for [" + client + "]: " + ex.getMessage();
// body
String login = "Not Available";
if ((requestInfo != null) && (requestInfo.getLogin() != null))
login = requestInfo.getLogin();
StringBuilder builder = new StringBuilder();
builder.append("<br><i>Logged in user:</i> " + login + "<br><br>");
builder.append("<i>Timestamp:</i> " + new Date() + "<br><br>");
String requestURI = "Not Available";
if ((requestInfo != null) && (requestInfo.getReq() != null)) {
requestURI = requestInfo.getReq().getRequestURI();
builder.append("<i>Request:</i> " + requestURI + "<br><br>");
@SuppressWarnings("unchecked")
Enumeration<String> parameterNames = requestInfo.getReq().getParameterNames();
if (parameterNames.hasMoreElements()) {
builder.append("<i>Query parameters: </i><br>");
while (parameterNames.hasMoreElements()) {
String key = (String) parameterNames.nextElement();
String value = requestInfo.getReq().getParameter(key);
builder.append(key + ": " + value + "<br>");
}
}
builder.append("<br>");
@SuppressWarnings("unchecked")
Enumeration<String> headerNames = requestInfo.getReq().getParameterNames();
if (headerNames.hasMoreElements()) {
builder.append("<i>Headers: </i><br>");
while (headerNames.hasMoreElements()) {
String key = (String) headerNames.nextElement();
String value = requestInfo.getReq().getParameter(key);
builder.append(key + ": " + value + "<br>");
}
}
}
builder.append("<br>");
builder.append("<i>Exception message:</i> " + ex.getMessage());
builder.append("<br><br>");
builder.append("<i>Stack trace:</i><br>");
builder.append(stackTraceToString(ex));
emailProp.bodyHtml = builder.toString();
GAEEmail.send(emailProp);
} catch (Exception exception) {
// This is usually called in response to an unhandled exception.
// just log the exception and swallow it
Logger logger = Logger.getLogger(Utils.class.getName());
logger.severe(stackTraceToString(exception));
}
}
public static String sanitizePhoneNo_do_not_use(String phoneNo) {
if (phoneNo == null)
return null;
// remove - and empty spaces
phoneNo = phoneNo.replaceAll(Pattern.quote("-"), "");
phoneNo = phoneNo.replaceAll(Pattern.quote(" "), "");
// replace leading 00 with +
phoneNo = phoneNo.replace("(^[0][0])", "+");
// remove leading zeros
phoneNo = phoneNo.replaceAll("^0+", "");
if (phoneNo.equals(""))
return null;
// if it does not contain + add it
if ((phoneNo.length() > 1) && (phoneNo.charAt(0) != '+'))
phoneNo = "+" + phoneNo;
return phoneNo;
}
public static String removeSpaceUnderscoreBracketAndHyphen(String s) {
if (s == null)
return null;
s = s.replaceAll(Pattern.quote("_"), "");
s = s.replaceAll(Pattern.quote(" "), "");
s = s.replaceAll(Pattern.quote("-"), "");
s = s.replaceAll(Pattern.quote("("), "");
s = s.replaceAll(Pattern.quote(")"), "");
return s;
}
public static String sanitizePhoneNo(String phoneNo, String country) {
if (phoneNo == null)
return null;
// remove - and empty spaces
phoneNo = phoneNo.replaceAll(Pattern.quote("-"), "");
phoneNo = phoneNo.replaceAll(Pattern.quote(" "), "");
// remove ( and )
phoneNo = phoneNo.replaceAll(Pattern.quote("("), "");
phoneNo = phoneNo.replaceAll(Pattern.quote(")"), "");
// add isd code if not specified
// for eg: if phone no is 93232152 and country is singapore make it
// +6593232152
if (country != null) {
CountryProp countryProp = RefData.getCountryProp(country);
if (countryProp != null) {
if (countryProp.numDigitsWOCountryCode != null) {
if ((phoneNo.length() == countryProp.numDigitsWOCountryCode) && !phoneNo.contains("+")) {
phoneNo = countryProp.isdCode + phoneNo;
}
}
}
}
// replace leading 00 with ""
phoneNo = phoneNo.replaceFirst("^(0*)", "");
if (phoneNo.equals(""))
return null;
// if it does not contain + add it
if ((phoneNo.length() > 1) && (phoneNo.charAt(0) != '+'))
phoneNo = "+" + phoneNo;
return phoneNo;
}
public static String sanitizeEmail(String email) {
if ((email == null) || email.equals(""))
return null;
return email;
}
// TODO: check if this method is really required. probably can be removed
public static <T> String toUserFriendlyString(Iterable<T> iterable) {
if (iterable == null)
return null;
StringBuilder builder = new StringBuilder();
int lineNo = 0;
for (T t : iterable) {
lineNo++;
builder.append("<br>" + lineNo + ") - " + t);
}
return builder.toString();
}
public static boolean isDifferentCaseInsensitive(String s1, String s2) {
if ((s1 == null) || (s2 == null))
return true;
return !s1.toLowerCase().equals(s2.toLowerCase());
}
public static double getWeightedAvg(List<Double> elements, List<Double> weights) {
ensure(!elements.isEmpty(), "No elements specified");
ensureEqual(elements.size(), weights.size(), "Num elements [" + elements.size()
+ "] does not match num weights [" + weights.size() + "]");
double numerator = 0.0;
double denominator = 0.0;
for (int i = 0; i < weights.size(); i++) {
denominator += weights.get(i);
numerator += elements.get(i) * weights.get(i);
}
ensure(denominator != 0, "Sum of weights is [0]");
return numerator / denominator;
}
public static String getFirstNChar(String s, int n) {
ensureNotNull(s, "s is null");
ensure(n >= 0, "invalid n [" + n + "]. should be greater than or equal to 0");
if (s.length() <= n)
return s;
return s.substring(0, n);
}
public static String readDataFromURL(String urlAddress) throws IOException {
URL url = new URL(urlAddress);
StringBuilder builder = new StringBuilder();
try (InputStreamReader inputStreamReader = new InputStreamReader(url.openStream())) {
try (BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
}
}
return builder.toString();
}
public static Set<String> getHrefs(String html) {
ensureNotNull(html, "html is null");
final String HREF_PATTERN = "href=\"([^\"]*)\"";
Matcher matcher = Pattern.compile(HREF_PATTERN).matcher(html);
Set<String> hrefs = new HashSet<>();
while (matcher.find()) {
String s = matcher.group(1);
hrefs.add(s);
}
return hrefs;
}
public static String getRandomAlphaNumericString(int numChars) {
ensure(numChars > 0, "numChars [" + numChars + "] is not positive");
String all = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
ensureEqual(62, all.length());
Random random = new Random();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < numChars; i++) {
char c = all.charAt(random.nextInt(all.length()));
builder.append(c);
}
return builder.toString();
}
public static <T> Iterable<T> safe(Iterable<T> iterable) {
return iterable == null ? Collections.<T>emptyList() : iterable;
}
public enum Currency {
SGD, USD, INR, MYR, AUD, GBP
}
public enum PaypalErrorType {
PAYPAL_SET_EXPRESS_CHECKOUT_FAILURE, PAYPAL_GET_EXPRESS_CHECKOUT_FAILURE, PAYPAL_DO_EXPRESS_CHECKOUT_FAILURE
}
public enum PhoneNoType {
LANDLINE, MOBILE
}
}