package esmska.data;
import java.beans.*;
import java.text.Collator;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
/** SMS Contact entity
* @author ripper
*/
public class Contact extends Object implements Comparable<Contact> {
private String name;
/** full phone number including the country code (starting with "+") */
private String number;
private String gateway;
// <editor-fold defaultstate="collapsed" desc="PropertyChange support">
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener) {
changeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
changeSupport.removePropertyChangeListener(listener);
}
// </editor-fold>
/** Create new contact with properties copied from provided contact */
public Contact(Contact c) {
this(c.getName(), c.getNumber(), c.getGateway());
}
/** Create new contact. For detailed parameters restrictions see individual setter methods. */
public Contact(String name, String number, String gateway) {
setName(name);
setNumber(number);
setGateway(gateway);
}
/** Copy all contact properties from provided contact to current contact */
public void copyFrom(Contact c) {
setName(c.getName());
setNumber(c.getNumber());
setGateway(c.getGateway());
}
// <editor-fold defaultstate="collapsed" desc="Get Methods">
/** Get contact name. Never null. */
public String getName() {
return this.name;
}
/** Get valid full phone number including the country code (starting with "+")
or empty string. Never null. */
public String getNumber() {
return this.number;
}
/** Get gateway. Never null. */
public String getGateway() {
return this.gateway;
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Set Methods">
/** Set contact name.
* @param name contact name. Null value is changed to empty string.
*/
public void setName(String name) {
if (name == null) {
name = "";
}
String oldName = this.name;
this.name = name;
changeSupport.firePropertyChange("name", oldName, name);
}
/** Set full phone number.
* @param number new contact number. Must be valid (see {@link #isValidNumber})
* or an empty string. Null value is changed to an empty string.
*/
public void setNumber(String number) {
if (number == null) {
number = "";
}
if (number.length() > 0 && !isValidNumber(number)) {
throw new IllegalArgumentException("Number is not valid: " + number);
}
String oldNumber = this.number;
this.number = number;
changeSupport.firePropertyChange("number", oldNumber, number);
}
/** Set contact gateway
* @param gateway new gateway. Null value is changed to "unknown" gateway.
*/
public void setGateway(String gateway) {
if (gateway == null) {
gateway = Gateway.UNKNOWN;
}
String oldGateway = this.gateway;
this.gateway = gateway;
changeSupport.firePropertyChange("gateway", oldGateway, gateway);
}
// </editor-fold>
/** Check validity of phone number
* @return true if number is in form +[0-9]{2,15} with valid country prefix,
* false otherwise
*/
public static boolean isValidNumber(String number) {
if (number == null) {
return false;
}
String prefix = CountryPrefix.extractCountryPrefix(number);
if (prefix == null) {
return false;
}
number = number.substring(prefix.length());
if (number.length() < 1 || number.length() + prefix.length() > 16) {
return false;
}
for (Character c : number.toCharArray()) {
if (!Character.isDigit(c)) {
return false;
}
}
return true;
}
/** Modify (phone) number into anonymous one
* @param number (phone) number, may be null
* @return the same string with all the numbers replaced by 'N'
*/
public static String anonymizeNumber(String number) {
if (number == null) {
return number;
} else {
return number.replaceAll("\\d", "N");
}
}
/** Try to extract valid number from some local format (like "(1) 222 333")
* and convert it into international number.
* @param number number in non-standard format; may be null
* @return parsed valid (international) number or null
*/
public static String parseNumber(String number) {
if (StringUtils.isEmpty(number)) {
return null;
}
boolean international = number.startsWith("+");
number = number.replaceAll("[^0-9]", "");
if (!international && StringUtils.isNotEmpty(Config.getInstance().getCountryPrefix())) {
number = Config.getInstance().getCountryPrefix() + number;
} else {
number = "+" + number;
}
if (isValidNumber(number)) {
return number;
} else {
return null;
}
}
@Override
public int compareTo(Contact c) {
Collator collator = Collator.getInstance();
return new CompareToBuilder().append(name, c.name, collator).
append(number, c.number, collator).
append(gateway, c.gateway, collator).toComparison();
}
@Override
public String toString() {
return getName();
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Contact)) {
return false;
}
Contact c = (Contact) obj;
return new EqualsBuilder().append(name, c.name).append(number, c.number).
append(gateway, c.gateway).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(337, 139).append(name).append(number).
append(gateway).toHashCode();
}
}