/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the Common Development
* and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at
* src/com/vodafone360/people/VODAFONE.LICENSE.txt or
* http://github.com/360/360-Engine-for-Android
* See the License for the specific language governing permissions and
* limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each file and
* include the License file at src/com/vodafone360/people/VODAFONE.LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the fields
* enclosed by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2010 Vodafone Sales & Services Ltd. All rights reserved.
* Use is subject to license terms.
*/
package com.vodafone360.people.tests.engine.contactsync;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import android.text.TextUtils;
import android.util.Log;
import com.vodafone360.people.datatypes.VCardHelper;
import com.vodafone360.people.datatypes.VCardHelper.Name;
import com.vodafone360.people.datatypes.VCardHelper.Organisation;
import com.vodafone360.people.datatypes.VCardHelper.PostalAddress;
import com.vodafone360.people.engine.contactsync.ContactChange;
import com.vodafone360.people.utils.VersionUtils;
public class ContactChangeHelper {
private static final int MAX_PHONE_NUMBERS_PER_CONTACT = 5;
private static final int MAX_EMAILS_PER_CONTACT = 5;
private static final int MAX_ADDRESSES_PER_CONTACT = 3;
private static final int MAX_ORGS_PER_CONTACT = 1;
private static final int MAX_TITLES_PER_CONTACT = 1;
private static final int MAX_WEBSITES_PER_CONTACT = 1;
private static final int MAX_BIRTHDAYS_PER_CONTACT = 1;
private static final int MAX_NOTES_PER_CONTACT = 1;
private static final int MAX_NAMES_PER_CONTACT = 1;
private static final int MAX_NICKNAMES_PER_CONTACT = 1;
private static final int MAX_NUM_DETAILS_ADD = 10;
private static final HashMap<Integer, Integer> sKeyMaxNumMap;
private static final int[] sKeyArray;
static {
sKeyArray = new int[9];
sKeyArray[0] = ContactChange.KEY_VCARD_NAME;
sKeyArray[1] = ContactChange.KEY_VCARD_NICKNAME;
sKeyArray[2] = ContactChange.KEY_VCARD_PHONE;
sKeyArray[3] = ContactChange.KEY_VCARD_EMAIL;
sKeyArray[4] = ContactChange.KEY_VCARD_ADDRESS;
sKeyArray[5] = ContactChange.KEY_VCARD_ORG;
sKeyArray[6] = ContactChange.KEY_VCARD_TITLE;
sKeyArray[7] = ContactChange.KEY_VCARD_URL;
sKeyArray[8] = ContactChange.KEY_VCARD_NOTE;
sKeyMaxNumMap = new HashMap<Integer, Integer>();
sKeyMaxNumMap.put(ContactChange.KEY_VCARD_NAME, MAX_NAMES_PER_CONTACT);
sKeyMaxNumMap.put(ContactChange.KEY_VCARD_NICKNAME, MAX_NICKNAMES_PER_CONTACT);
sKeyMaxNumMap.put(ContactChange.KEY_VCARD_PHONE, MAX_PHONE_NUMBERS_PER_CONTACT);
sKeyMaxNumMap.put(ContactChange.KEY_VCARD_EMAIL, MAX_EMAILS_PER_CONTACT);
sKeyMaxNumMap.put(ContactChange.KEY_VCARD_ADDRESS, MAX_ADDRESSES_PER_CONTACT);
sKeyMaxNumMap.put(ContactChange.KEY_VCARD_ORG, MAX_ORGS_PER_CONTACT);
sKeyMaxNumMap.put(ContactChange.KEY_VCARD_TITLE, MAX_TITLES_PER_CONTACT);
sKeyMaxNumMap.put(ContactChange.KEY_VCARD_URL, MAX_WEBSITES_PER_CONTACT);
sKeyMaxNumMap.put(ContactChange.KEY_VCARD_NOTE, MAX_NOTES_PER_CONTACT);
}
private static Random sRn = new Random();
private static final String[] mNameTitleList = {
"Mr.",
"Mrs.",
"Miss",
"Prof.",
"Dr.",
"Eng."
};
public static void printContactChange(ContactChange cc) {
Log.i("CC", "--------------- START ---------------");
Log.d("CC",
"Key:"+cc.getKeyToString()+"("+cc.getKey()+")\n"+
"Value:"+cc.getValue()+"\n"+
"Flags:"+cc.getFlags()+"\n"+
"Type:"+cc.getType()+"\n"+
"IDS(IntCntID:"+cc.getInternalContactId()+
", IntDtlID:"+cc.getInternalDetailId()+
", BckndCntID:"+cc.getBackendContactId()+
", BckndDtlID:"+cc.getBackendDetailId()+
", NABCntID:"+cc.getNabContactId()+
", NABDtlID:"+cc.getNabDetailId()+")");
Log.i("CC", "--------------- END --------------");
}
public static void printContactChangeList(ContactChange[] ccList) {
final int length = ccList.length;
Log.i("CCLIST", "############### START ###############");
for(int i = 0; i < length; i++) {
final ContactChange cc = ccList[i];
printContactChange(cc);
}
Log.i("CCLIST", "############### END ###############");
}
public static boolean areChangesEqual(ContactChange a, ContactChange b, boolean compareAll) {
if(a.getKey() != b.getKey()) {
return false;
}
// just for convenience
final int key = a.getKey();
if(!VersionUtils.is2XPlatform() && key == ContactChange.KEY_VCARD_NAME) {
// Need to convert to raw string or else we can't compare them because of NAB 1.X limitations
final Name nameA = VCardHelper.getName(a.getValue());
final Name nameB = VCardHelper.getName(b.getValue());
final String nameAStr = nameA.toString();
final String nameBStr = nameB.toString();
if(!TextUtils.equals(nameAStr, nameBStr)) {
return false;
}
} else if(!VersionUtils.is2XPlatform() && key == ContactChange.KEY_VCARD_ADDRESS) {
// Need to convert to raw string or else we can't compare them because of NAB 1.X limitations
final PostalAddress addressA = VCardHelper.getPostalAddress(a.getValue());
final PostalAddress addressB = VCardHelper.getPostalAddress(b.getValue());
// Need to also remove \n's that were put there by .toString
final String addressAStr = addressA.toString().replaceAll("\n", "");
final String addressBStr = addressB.toString().replaceAll("\n", "");
if(!TextUtils.equals(addressAStr, addressBStr)) {
return false;
}
} else if(!VersionUtils.is2XPlatform() && key == ContactChange.KEY_VCARD_ORG) {
// Org on 1.X does not support department, need to NOT compare that
final Organisation orgA = VCardHelper.getOrg(a.getValue());
final Organisation orgB = VCardHelper.getOrg(b.getValue());
if(!TextUtils.equals(orgA.name, orgB.name)) {
return false;
}
} else if(!TextUtils.equals(a.getValue(), b.getValue())) {
return false;
}
switch(key) {
case ContactChange.KEY_VCARD_ORG:
case ContactChange.KEY_VCARD_TITLE:
case ContactChange.KEY_VCARD_PHONE:
case ContactChange.KEY_VCARD_EMAIL:
case ContactChange.KEY_VCARD_ADDRESS:
// NAB may have changed these fields to preferred even though they were inserted as not preferred!
final int flagsWithoutPreferredA = a.getFlags() & ~ContactChange.FLAG_PREFERRED;
final int flagsWithoutPreferredB = b.getFlags() & ~ContactChange.FLAG_PREFERRED;
if(flagsWithoutPreferredA != flagsWithoutPreferredB) {
return false;
}
break;
default:
if(a.getFlags() != b.getFlags()) {
return false;
}
break;
}
if(VersionUtils.is2XPlatform() && a.getFlags() != b.getFlags()) {
return false;
} else if(!VersionUtils.is2XPlatform()) {
}
if(compareAll) {
if(a.getType() != b.getType()) {
return false;
}
if(a.getInternalContactId() != b.getInternalContactId()) {
return false;
}
if(a.getInternalDetailId() != b.getInternalDetailId()) {
return false;
}
if(a.getBackendContactId() != b.getBackendContactId()) {
return false;
}
if(a.getBackendDetailId() != b.getBackendDetailId()) {
return false;
}
if(a.getNabContactId() != b.getNabContactId()) {
return false;
}
if(a.getNabDetailId() != b.getNabDetailId()) {
return false;
}
}
return true;
}
public static boolean areChangeListsEqual(ContactChange[] a,
ContactChange[] b, boolean compareAll) {
final int aLength = a.length;
final int bLength = b.length;
if(aLength != bLength) {
printContactChangeList(a);
printContactChangeList(b);
return false;
}
for(int i = 0; i < aLength; i++) {
final ContactChange ccA = a[i];
final ContactChange ccB = b[i];
if(!areChangesEqual(ccA, ccB, compareAll)) {
Log.e("CC COMPARISON", "Contact Change comparison mismatch, ContactChange A to follow:");
printContactChange(ccA);
Log.e("CC COMPARISON", "Contact Change comparison mismatch, ContactChange B to follow:");
printContactChange(ccB);
return false;
}
}
return true;
}
public static boolean areUnsortedChangeListsEqual(ContactChange[] a, ContactChange[] b, boolean compareAll) {
final int aLength = a.length;
final int bLength = b.length;
if(aLength != bLength) {
printContactChangeList(a);
printContactChangeList(b);
return false;
}
for(int i = 0; i < aLength; i++) {
final ContactChange ccA = a[i];
boolean matchFound = false;
for(int j = 0; j < bLength; j++) {
final ContactChange ccB = a[j];
if(ccA.getKey() == ccB.getKey() && ccA.getNabDetailId() == ccB.getNabDetailId()) {
if(areChangesEqual(ccA, ccB, compareAll)) {
matchFound = true;
break;
}
}
}
if(!matchFound) {
Log.e("CONTACT COMPARISON", "Contact List Unsorted comparison because of mismatch, List A to follow:");
printContactChangeList(a);
Log.e("CONTACT COMPARISON", "Contact List Unsorted comparison because of mismatch, List B to follow:");
printContactChangeList(b);
return false;
}
}
return true;
}
public static boolean isUniqueKeyForContact(int key) {
final Integer maxNum = sKeyMaxNumMap.get(key);
return maxNum != null && maxNum == 1;
}
public static ContactChange[] randomContact(long internalContactId, long backendContactId, long nabContactId) {
final List<ContactChange> ccList = new ArrayList<ContactChange>();
int numNames = 0,
numNicknames = 0,
numEmails = 0,
numPhones = 0,
numAddresses = 0,
numTitles = 0,
numWebsites = 0,
numNotes = 0,
numOrgs = 0,
numBirthdays = 0;
numNames = valueForLikelihoodPercentage(85, MAX_NAMES_PER_CONTACT); // 85% likely
if(VersionUtils.is2XPlatform()) {
numNicknames = valueForLikelihoodPercentage(30, MAX_NICKNAMES_PER_CONTACT); // 30% likely
numBirthdays = valueForLikelihoodPercentage(25, MAX_BIRTHDAYS_PER_CONTACT); // 25% likely
}
numEmails = randomPositiveInt(MAX_EMAILS_PER_CONTACT);
// Always create at least a phone number so that an empty cc list is not possible
numPhones = 1 + randomPositiveInt(MAX_PHONE_NUMBERS_PER_CONTACT -1);
numAddresses = randomPositiveInt(MAX_ADDRESSES_PER_CONTACT);
numTitles = valueForLikelihoodPercentage(40, MAX_TITLES_PER_CONTACT);
if(VersionUtils.is2XPlatform()) {
numWebsites = valueForLikelihoodPercentage(35, MAX_WEBSITES_PER_CONTACT);
}
numNotes = valueForLikelihoodPercentage(35, MAX_NOTES_PER_CONTACT); // 35% likely
numOrgs = valueForLikelihoodPercentage(40, MAX_ORGS_PER_CONTACT);
generateRandomChangesForKey(ccList, ContactChange.KEY_VCARD_NAME,
internalContactId, backendContactId, nabContactId, numNames);
generateRandomChangesForKey(ccList, ContactChange.KEY_VCARD_NOTE,
internalContactId, backendContactId, nabContactId, numNotes);
generateRandomChangesForKey(ccList, ContactChange.KEY_VCARD_NICKNAME,
internalContactId, backendContactId, nabContactId, numNicknames);
generateRandomChangesForKey(ccList, ContactChange.KEY_VCARD_PHONE,
internalContactId, backendContactId, nabContactId, numPhones);
generateRandomChangesForKey(ccList, ContactChange.KEY_VCARD_EMAIL,
internalContactId, backendContactId, nabContactId, numEmails);
generateRandomChangesForKey(ccList, ContactChange.KEY_VCARD_DATE,
internalContactId, backendContactId, nabContactId, numBirthdays);
generateRandomChangesForKey(ccList, ContactChange.KEY_VCARD_ADDRESS,
internalContactId, backendContactId, nabContactId, numAddresses);
generateRandomChangesForKey(ccList, ContactChange.KEY_VCARD_URL,
internalContactId, backendContactId, nabContactId, numWebsites);
generateRandomChangesForKey(ccList, ContactChange.KEY_VCARD_ORG,
internalContactId, backendContactId, nabContactId, numOrgs);
generateRandomChangesForKey(ccList, ContactChange.KEY_VCARD_TITLE,
internalContactId, backendContactId, nabContactId, numTitles);
final int numOrgTitlePairs = Math.min(numOrgs, numTitles);
if(numOrgTitlePairs > 0) {
final int ccListSize = ccList.size();
// Have to make the flags for each pair have the same values so that comparison is safe later
for(int i = 0; i < numOrgTitlePairs; i++) {
// get org flags
final int orgFlags = ccList.get((ccListSize - (numOrgs + numTitles)) + i).getFlags();
// copy over flags from org to title
ccList.get(ccListSize - numOrgTitlePairs + i).setFlags(orgFlags);
}
}
return ccList.toArray(new ContactChange[ccList.size()]);
}
public static ContactChange[] randomContactUpdate(ContactChange[] contact) {
final int originalDetailsNum = contact.length;
final long internalCntId = contact[0].getInternalContactId();
final long backendCntId = contact[0].getBackendContactId();
final long nabCntId = contact[0].getNabContactId();
int numDeletedDetails = 0,
curNumDeletedDetails = 0,
numAddedDetails = 0,
curNumAddedDetails = 0,
numChangedDetails = 0,
curNumChangedDetails = 0;
// At best we can only delete all but one detail
numDeletedDetails = randomPositiveInt(originalDetailsNum - 1);
// At best we can only change all details minus the ones we will delete
numChangedDetails = randomPositiveInt(originalDetailsNum - numDeletedDetails);
// Reasonable maximum of details we can add
numAddedDetails = randomPositiveInt(MAX_NUM_DETAILS_ADD);
final int updateCcListSize = numAddedDetails + numChangedDetails + numDeletedDetails;
ContactChange[] updateCcList =
new ContactChange[updateCcListSize];
for(int i = 0; i < updateCcListSize; i++) {
if(curNumChangedDetails < numChangedDetails) {
updateCcList[i] = generateUpdateDetailChange(contact[i]);
curNumChangedDetails++;
continue;
}
if (curNumDeletedDetails < numDeletedDetails) {
updateCcList[i] = generateDeleteDetailChange(contact[i]);
curNumDeletedDetails++;
continue;
}
if(curNumAddedDetails < numAddedDetails) {
int key;
do {
// get a random key and don't let it be a unique key to simplify things
key = randomKey();
if(isKeyPlatformSupported(key)) {
if(!isUniqueKeyForContact(key) ||
(isUniqueKeyForContact(key) &&
!isKeyPresent(key, updateCcList) &&
!isKeyPresent(key, contact))) {
break;
}
}
} while(true);
// The new detail, preferred flag not allowed to simplify things a little
final ContactChange addDetailCc = randomContactChange(key, internalCntId, backendCntId, nabCntId, false);
//addDetailCc.setInternalDetailId(randomPositiveLong());
addDetailCc.setType(ContactChange.TYPE_ADD_DETAIL);
updateCcList[i] = addDetailCc;
curNumAddedDetails++;
}
}
return updateCcList;
}
public static ContactChange[] generatedUpdatedContact(ContactChange[] contact, ContactChange[] update) {
if(update == null || update.length == 0) {
return contact;
}
final List<ContactChange> updatedContact = new ArrayList<ContactChange>();
final int contactSize = contact.length;
final int updateSize = update.length;
for(int i = 0; i < contactSize; i++) {
ContactChange cc = contact[i];
int updateType = ContactChange.TYPE_UNKNOWN;
if(updateSize > i) {
updateType = update[i].getType();
}
if(updateType == ContactChange.TYPE_UPDATE_DETAIL) {
cc = update[i];
} else if(updateType == ContactChange.TYPE_DELETE_DETAIL) {
continue;
}
updatedContact.add(cc);
}
for(int i = 0; i < updateSize; i++) {
final ContactChange cc = update[i];
//final int key = cc.getKey();
if(cc.getType() == ContactChange.TYPE_ADD_DETAIL) {
//updatedContact.add(lastIndexForKeyInCcList(key, updatedContact) + 1, cc);
// Since we are using areUnsortedChangeListsEqual to compare we can just add instead of above
updatedContact.add(cc);
}
}
return updatedContact.toArray(new ContactChange[updatedContact.size()]);
}
/**
* Finds the last index for the specified key.
* This method uses recursion.
*/
private static int lastIndexForKeyInCcList(int key, List<ContactChange> ccList) {
if(ccList == null || ccList.size() == 0) {
return -1;
}
final int listSize = ccList.size();
for(int i = listSize - 1; i > -1; i--) {
if(ccList.get(i).getKey() == key) {
return i;
}
}
// Yes, this is recursion...
switch(key) {
case ContactChange.KEY_VCARD_TITLE:
return lastIndexForKeyInCcList(ContactChange.KEY_VCARD_ORG, ccList);
case ContactChange.KEY_VCARD_ORG:
return lastIndexForKeyInCcList(ContactChange.KEY_VCARD_ADDRESS, ccList);
case ContactChange.KEY_VCARD_ADDRESS:
return lastIndexForKeyInCcList(ContactChange.KEY_VCARD_EMAIL, ccList);
case ContactChange.KEY_VCARD_EMAIL:
return lastIndexForKeyInCcList(ContactChange.KEY_VCARD_PHONE, ccList);
case ContactChange.KEY_VCARD_PHONE:
return lastIndexForKeyInCcList(ContactChange.KEY_VCARD_NICKNAME, ccList);
case ContactChange.KEY_VCARD_NICKNAME:
return lastIndexForKeyInCcList(ContactChange.KEY_VCARD_NOTE, ccList);
case ContactChange.KEY_VCARD_NOTE:
return lastIndexForKeyInCcList(ContactChange.KEY_VCARD_NAME, ccList);
}
return -1;
}
public static boolean isKeyPresent(int key, ContactChange[] ccList) {
if(ccList == null || ccList.length == 0) {
return false;
}
final int listSize = ccList.length;
for(int i = listSize - 1; i > -1; i--) {
if(ccList[i] != null && ccList[i].getKey() == key) {
return true;
}
}
return false;
}
private static boolean isKeyPlatformSupported(int key) {
switch (key) {
case ContactChange.KEY_VCARD_TITLE:
case ContactChange.KEY_VCARD_ORG:
case ContactChange.KEY_VCARD_ADDRESS:
case ContactChange.KEY_VCARD_EMAIL:
case ContactChange.KEY_VCARD_PHONE:
case ContactChange.KEY_VCARD_NOTE:
case ContactChange.KEY_VCARD_NAME:
return true;
case ContactChange.KEY_VCARD_URL:
case ContactChange.KEY_VCARD_NICKNAME:
return VersionUtils.is2XPlatform();
}
return false;
}
private static ContactChange generateUpdateDetailChange(ContactChange cc) {
if(cc == null) {
return null;
}
final int key = cc.getKey();
boolean changed = false;
String value = cc.getValue();
int flags = cc.getFlags();
int newFlags = flags;
if(randomTrue()) {
value = randomValue(key);
changed = true;
}
if(randomTrue()) {
flags = randomFlags(key, false);
if(newFlags != flags) {
changed = true;
}
}
if(!changed) {
value = randomValue(key);
}
final ContactChange updateDetailCc = new ContactChange(key, value, newFlags);
updateDetailCc.setType(ContactChange.TYPE_UPDATE_DETAIL);
updateDetailCc.setInternalContactId(cc.getInternalContactId());
updateDetailCc.setInternalDetailId(cc.getInternalDetailId());
updateDetailCc.setBackendContactId(cc.getBackendContactId());
updateDetailCc.setBackendDetailId(cc.getBackendDetailId());
updateDetailCc.setNabContactId(cc.getNabContactId());
updateDetailCc.setNabDetailId(cc.getNabDetailId());
return updateDetailCc;
}
private static ContactChange generateDeleteDetailChange(ContactChange cc) {
if(cc == null) {
return null;
}
final ContactChange deleteDetailCc = new ContactChange();
deleteDetailCc.setKey(cc.getKey());
deleteDetailCc.setType(ContactChange.TYPE_DELETE_DETAIL);
deleteDetailCc.setInternalContactId(cc.getInternalContactId());
deleteDetailCc.setInternalDetailId(cc.getInternalDetailId());
deleteDetailCc.setBackendContactId(cc.getBackendContactId());
deleteDetailCc.setBackendDetailId(cc.getBackendDetailId());
deleteDetailCc.setNabContactId(cc.getNabContactId());
deleteDetailCc.setNabDetailId(cc.getNabDetailId());
return deleteDetailCc;
}
private static void generateRandomChangesForKey(
List<ContactChange> ccList, int key,
long internalContactId, long backendContactId,
long nabContactId, int numChanges) {
boolean preferredSelected = false;
for(int i = 0; i < numChanges; i++) {
ContactChange cc = randomContactChange(key, internalContactId, backendContactId, nabContactId, !preferredSelected);
if(!preferredSelected) {
preferredSelected =
(cc.getFlags() & ContactChange.FLAG_PREFERRED) == ContactChange.FLAG_PREFERRED;
}
ccList.add(cc);
}
}
private static ContactChange randomContactChange(int key,
long internalContactId, long backendContactId, long nabContactId, boolean allowPreferred) {
ContactChange cc = randomContactChange(key, allowPreferred);
cc.setInternalContactId(internalContactId);
cc.setBackendContactId(backendContactId);
cc.setNabContactId(nabContactId);
return cc;
}
private static ContactChange randomContactChange(int key, boolean allowPreferred) {
return new ContactChange(key, randomValue(key), randomFlags(key, allowPreferred));
}
private static int randomKey() {
return sKeyArray[randomPositiveInt(sKeyArray.length - 1)];
}
private static Name randomName() {
String firstname = null,
surname = null,
midname = null,
suffix = null,
title = null;
if(randomTrue()) {
firstname = randomString();
}
if(randomTrue()) {
surname = randomString();
}
if(randomTrue()) {
midname = randomString();
}
if(randomTrue()) {
if(randomTrue()) {
title = randomString();
} else {
title = mNameTitleList[randomPositiveInt(mNameTitleList.length)];
}
}
if(randomTrue()) {
suffix = randomString();
}
if(randomTrue()) {
firstname = randomString();
}
Name name = new Name();
if(firstname == null &&
surname == null) {
/* So that we have one part not null!
* Note that we ignored middle name, suffix and title in the above check
* The reason for doing so is that 2.X NAB cannot work with just middle name, prefix and suffix fields!
*/
firstname = randomString();
}
name.firstname = firstname;
name.midname = midname;
name.surname = surname;
name.title = title;
name.suffixes = suffix;
return name;
}
private static PostalAddress randomAddress() {
String addressLine1 = null,
addressLine2 = null,
city = null,
county = null,
pobox = null,
postcode = null,
country = null;
if(randomTrue()) {
pobox = randomString();
}
if(randomTrue()) {
addressLine1 = randomString();
}
if(randomTrue()) {
addressLine2 = randomString();
}
if(randomTrue()) {
city = randomString();
}
if(randomTrue()) {
county = randomString();
}
if(randomTrue()) {
postcode = randomNumbersString();
}
if(randomTrue()) {
country = randomString();
}
PostalAddress address = new PostalAddress();
if( pobox != null
|| addressLine1 != null
|| addressLine2 != null
|| city != null
|| county != null
|| postcode != null
|| country != null) {
address.addressLine1 = addressLine1;
address.addressLine2 = addressLine2;
address.postOfficeBox = pobox;
address.postCode = postcode;
address.city = city;
address.county = county;
address.country = country;
} else {
// So that we have one part not null
address.addressLine1 = randomString();
}
return address;
}
private static Organisation randomOrganization() {
String company = null,
department = null;
if(randomTrue()) {
company = randomString();
}
if(randomTrue()) {
// Department only matters in 2.X
department = randomString();
}
Organisation org = new Organisation();
if(company == null && department == null ||
(!VersionUtils.is2XPlatform() && company == null)) {
// So that we have one part not null
// Also in 1.X we should have a company because department doesn't matter
company = randomString();
}
org.name = company;
org.unitNames.add(department);
return org;
}
private static String randomValue(int key) {
switch (key) {
case ContactChange.KEY_VCARD_NAME:
return VCardHelper.makeName(randomName());
case ContactChange.KEY_VCARD_PHONE:
return randomPhoneNumber();
case ContactChange.KEY_VCARD_EMAIL:
return randomEmail();
case ContactChange.KEY_VCARD_ADDRESS:
return VCardHelper.makePostalAddress(randomAddress());
case ContactChange.KEY_VCARD_ORG:
return VCardHelper.makeOrg(randomOrganization());
case ContactChange.KEY_VCARD_DATE:
return randomBirthday(); // Only birthday supported currently
}
return randomString();
}
// private static String randomUpdatedValue(ContactChange cc) {
// final int key = cc.getKey();
// switch(key) {
// case ContactChange.KEY_VCARD_NAME:
// // get old value first
// final Name name = VCardHelper.getName(cc.getValue());
// final Name randomName = randomName();
// if(!TextUtils.isEmpty(randomName.firstname)) {
// name.firstname = randomName.firstname;
// }
//
// if(!TextUtils.isEmpty(randomName.midname)) {
// name.firstname = randomName.midname;
// }
//
// if(!TextUtils.isEmpty(randomName.surname)) {
// name.firstname = randomName.surname;
// }
//
// if(!TextUtils.isEmpty(randomName.title)) {
// name.firstname = randomName.title;
// }
//
// if(!TextUtils.isEmpty(randomName.suffixes)) {
// name.firstname = randomName.suffixes;
// }
//
// return VCardHelper.makeName(name);
// case ContactChange.KEY_VCARD_ADDRESS:
// final PostalAddress address = VCardHelper.getPostalAddress(cc.getValue());
// final PostalAddress randomAddress =
// break;
// case ContactChange.KEY_VCARD_ORG:
// break;
//
// }
//
// return randomValue(key);
// }
private static int randomPhoneFlags() {
if(randomTrue()) {
return ContactChange.FLAG_CELL;
}
if(randomTrue()) {
return ContactChange.FLAG_HOME;
}
if(randomTrue()) {
return ContactChange.FLAG_WORK;
}
if(VersionUtils.is2XPlatform() && randomTrue()) {
return ContactChange.FLAGS_WORK_CELL;
}
if(VersionUtils.is2XPlatform() && randomTrue()) {
return ContactChange.FLAG_FAX;
}
if(randomTrue()) {
return ContactChange.FLAGS_WORK_FAX;
}
if(randomTrue()) {
return ContactChange.FLAGS_HOME_FAX;
}
return ContactChange.FLAG_NONE;
}
private static int randomBasicFlags() {
if(randomTrue()) {
return ContactChange.FLAG_HOME;
}
if(randomTrue()) {
return ContactChange.FLAG_WORK;
}
return ContactChange.FLAG_NONE;
}
private static int randomFlags(int key, boolean allowPreferred) {
int flags = ContactChange.FLAG_NONE;
switch(key) {
case ContactChange.KEY_VCARD_PHONE:
flags = randomPhoneFlags();
break;
case ContactChange.KEY_VCARD_URL:
case ContactChange.KEY_VCARD_ADDRESS:
case ContactChange.KEY_VCARD_EMAIL:
flags = randomBasicFlags();
break;
case ContactChange.KEY_VCARD_TITLE:
case ContactChange.KEY_VCARD_ORG:
if(randomTrue()) {
flags = ContactChange.FLAG_WORK;
}
break;
case ContactChange.KEY_VCARD_DATE:
// Only birthday currently supported
flags = ContactChange.FLAG_BIRTHDAY;
// fall through
default:
allowPreferred = false;
break;
}
if(allowPreferred && randomTrue()) {
flags|= ContactChange.FLAG_PREFERRED;
}
return flags;
}
/**
* Returns provided value if the probability Threshold given is met
* Otherwise returns zero
* @param treshold
* @param value
* @return value or zero
*/
private static int valueForLikelihoodPercentage(int percentage, int value) {
return randomPositiveInt(100) < percentage ? value : 0;
}
private static int randomPositiveInt(int limit) {
return Math.abs(sRn.nextInt() % limit);
}
private static long randomPositiveLong() {
return Math.abs(sRn.nextLong());
}
private static int rand(int lo, int hi) {
int n = hi - lo + 1;
int i = sRn.nextInt() % n;
if (i < 0)
i = -i;
return lo + i;
}
private static String randomString(int lo, int hi, char loChar, char hiChar) {
int n = rand(lo, hi);
byte b[] = new byte[n];
for (int i = 0; i < n; i++)
b[i] = (byte)rand(loChar, hiChar);
return new String(b, 0);
}
private static String randomString() {
return randomString(4, 20, 'a', 'z');
}
private static String randomPhoneNumber() {
return "+"+randomString(4, 12, '0', '9');
}
private static String randomNumbersString() {
return randomString(4, 12, '0', '9');
}
private static String randomEmail() {
return randomString(4, 15, 'a', 'z')+"@"+randomString(4, 10, 'a', 'z')+".com";
}
private static Calendar randomDate() {
Date date = new Date(sRn.nextLong());
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar;
}
private static String randomBirthday() {
final Calendar calendar = Calendar.getInstance();
Calendar randomDate = null;
do {
randomDate = randomDate();
final int currentYear = calendar.get(Calendar.YEAR);
final int birthdayYear = currentYear - randomPositiveInt(100); // Maximum 100 years old
randomDate.set(Calendar.YEAR, birthdayYear);
} while(calendar.compareTo(randomDate) >= 0);
final StringBuilder sb = new StringBuilder();
sb.append(randomDate.get(Calendar.DAY_OF_MONTH));
sb.append('-');
sb.append((randomDate.get(Calendar.MONTH)+1));
sb.append('-');
sb.append(randomDate.get(Calendar.YEAR));
return sb.toString();
}
private static boolean randomTrue() {
return sRn.nextBoolean();
}
}