/**
* \package com.bluevia.android.commons.data This package contains basic classes for common subtypes used by other entity data of the Bluevia APIs.
*/
package com.bluevia.android.commons.data;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.util.Log;
import com.bluevia.android.commons.Entity;
/**
* Class representing UserId identification
* This class may be used to identify the user on the request.
* For example, when sending an SMS, the recipient of the SMS may be identified using this class
* There are 6 types of UserIds types:
* <ul>
* <li>PhoneNumber. Phone Number value must be set in mUserIdValue
* <li>Any Uri. URI value must be set in mUserIdValue
* <li>IPV4. IPV4 value must be set in mUserIdValue
* <li>IPV6. IPV6 value must be set in mUserIdValue
* <li>Alias. Alias value must be set in mUserIdValue
* <li>Other Id. Id name must be set at mOtherType and Id value value must be set in mUserIdValue
* </ul>
*
* This implementation is not synchronized
*
* @author Telefonica R&D
*
*
*/
public class UserId implements Entity {
/**
* Enum Type to indicate the type of the value that identifies the user.
* Available types are:
* <ul>
* <li> PHONE_NUMBER: a Telephone number.</li>
* <li> ANY_URI: a Uri</li>
* <li> IPV4_ADDRESS: an IP 4 address</li>
* <li> IPV6_ADDRESS: an IP 6 address</li>
* <li> ALIAS: an arbitrary alias</li>
* <li> OTHER_ID: another identity</li>
* <ul>
* @author Telefonica R&D
*
*/
public static enum Type {
PHONE_NUMBER,
ANY_URI,
IPV4_ADDRESS,
IPV6_ADDRESS,
ALIAS,
OTHER_ID,
}
/// @cond private
private static final String TAG = "UserId";
private Type mType = null;
private String mUserIdValue = null;
private String mOtherType = null;
///@endcond
/**
* Instantiates a new UserId type.
*/
public UserId(){
super();
}
/**
* Instantiates a new UserId type.
*/
public UserId(Type mType, String mUserIdValue) {
super();
this.mType = mType;
this.mUserIdValue = mUserIdValue;
}
/**
* Gets the UserId Type
* @return the UserId type
*/
public Type getType() {
return mType;
}
/**
* Sets the Userid type
* @param type the type of the UserId
*/
public void setType(Type type) {
this.mType = type;
}
/**
* Gets the UserId value for the type set
* @return the UserId value
*/
public String getUserIdValue() {
return mUserIdValue;
}
/**
* Sets the UserId value for the type set
* @param userIdValue the UserId value
*/
public void setUserIdValue(String userIdValue) {
this.mUserIdValue = userIdValue;
}
/**
* When the type use id "Other Type", The Type value must be set using this method
* This method gets the value of the other type name.
* @return the Other Type name
*/
public String getOtherType() {
return mOtherType;
}
/**
* When the type use id "Other Type", The Type value must be set using this method
* * This method sets the other type name.
* @param otherType
*/
public void setOtherType(String otherType) {
this.mOtherType = otherType;
}
public boolean isValid() {
if (mType == null)
return false;
switch (mType) {
case PHONE_NUMBER:
Log.d(TAG, "validando phonenumber");
return validateAsPhoneNumber();
case IPV4_ADDRESS:
return validateAsIPv4();
case IPV6_ADDRESS:
return validateAsIPv6();
case ANY_URI:
return validateAnyURI();
case ALIAS:
return validateAlias();
case OTHER_ID:
return validateOtherType();
}
return false;
}
@Override
public boolean equals(Object o) {
if (o instanceof UserId && o != null) {
UserId userId = (UserId) o;
return (userId.getType().equals(this.mType)
&& userId.mUserIdValue.equals(this.mUserIdValue)
&& (this.mType == Type.OTHER_ID ? userId.getOtherType().equals(mOtherType) : true));
}
return super.equals(o);
}
@Override
public int hashCode(){
final int PRIME = 31;
int hash = 1;
hash = PRIME * hash + mType.ordinal();
hash = PRIME * hash + mUserIdValue.hashCode();
if (mType == Type.OTHER_ID && mOtherType != null)
hash = PRIME * hash + mOtherType.hashCode();
return hash;
}
/**
* Returns the corresponding String representation for each UserId type.
*
* @return the corresponding String representation for each UserId type.
*/
public String getStringType(){
switch(mType){
case ALIAS:
return "alias";
case ANY_URI:
return "anyUri";
case IPV4_ADDRESS:
return "ipAddress"; //TODO revisar IPV4 e IPV6
case IPV6_ADDRESS:
return "ipAddress";
case PHONE_NUMBER:
return "phoneNumber";
case OTHER_ID:
return mOtherType;
}
return null;
}
/// @cond private
private boolean validateAsPhoneNumber() {
boolean isValid = false;
Log.d(TAG, "Starting validateAsPhoneNumber");
if (mUserIdValue != null) {
// Expression to validate XSD pattern <xsd:pattern value="[0-9]+"/> applied to
// UseridType phoneNumber (E164 Type)
// A phone number, is a maximum of 15 digits following the E164 format
String expression ="\\d{1,15}$";
Pattern pattern = Pattern.compile(expression);
Matcher matcher = pattern.matcher(mUserIdValue);
if(matcher.matches()){
isValid = true;
} else {
Log.e(TAG,"Phone Number Address " + mUserIdValue + " does not follow phone pattern");
}
} else {
Log.e(TAG,"Phone Number Address must not be null");
}
Log.d(TAG, "ValidateAsPhonenumber: " + isValid);
return isValid;
}
private boolean validateAsIPv4() {
boolean isValid = false;
// We use the BlueVia expression to validate IPv4 addresses, although is wrong
// TODO Let see if BlueVia mantain the expression or finds a better one
String expression = "((0|(1[0-9]{0,2})|(2(([0-4][0-9]?)|(5[0-5]?)|([6-9]?)))|([3-9][0-9]?))\\.){3}(0|(1[0-9]{0,2})|(2(([0-4][0-9]?)|(5[0-5]?)|([6-9]?)))|([3-9][0-9]?))$";
// Other better regex used on Internet to validate ipv4 address
//String expression ="((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)$";
Pattern pattern = Pattern.compile(expression);
Matcher matcher = pattern.matcher(mUserIdValue);
if(matcher.matches()){
isValid = true;
} else {
Log.e (TAG,"IPv4 Address " + mUserIdValue + " does not follow IPv4 pattern");
}
return isValid;
}
/*
* This is the best way to validate all IPv4 address because using a good pattern is really difficult
* However, the BlueVia XML use a "wrong" pattern to validate IPv4 address. We are using this pattern for
* compatibility, because if we use other pattern they can check the XML and say it is wrong
private boolean validateAsIPv4(String mUserIdValue) {
try {
java.net.Inet4Address.getByName(mUserIdValue);
return true;
} catch(Exception e) {
return false;
}
}*/
private boolean validateAsIPv6() {
boolean isValid = false;
// We use the BlueVia expression to validate IPv6 addresses, although is wrong
// TODO Let see if BlueVia mantain the expression or finds a better one
// Valid addresses: 1080:0:0:0:8:800:200C:417A 1080::8:800:200C:417A ::FFFF:129.144.52.38 ::129.144.52.38 "::FFFF:d",
// Invalid addresses ::FFFF:d.d.d ::FFFF:d.d ::d.d.d ::d.d
String expression = "(([0-9a-fA-F]+:){7}[0-9a-fA-F]+)|(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?::(([0-9a-fA-F]+:)*[0-9a-fA-F]+)?";
// Other regex used on Internet to validate ipv6 address
//String expression = "\\A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\z";
Pattern pattern = Pattern.compile(expression);
Matcher matcher = pattern.matcher(mUserIdValue);
if(matcher.matches()){
isValid = true;
} else {
Log.e (TAG,"IPv6 Address " + mUserIdValue + " does not follow IPv6 pattern");
}
return isValid;
}
/*
* This is the best way to validate all IPv6 address because using a good pattern is really difficult
* However, the BlueVia XML use a "wrong" pattern to validate IPv6 address. We are using this pattern for
* compatibility, because if we use other pattern they can check the XML and say it is wrong
private boolean validateAsIPv6() {
try {
java.net.Inet6Address.getByName(mUserIdValue);
return true;
} catch(Exception e) {
return false;
}
}*/
private boolean validateAnyURI () {
//URI validation is done using Exceptions because using a pattern is difficult
// However there may be problems with encoded non ASCII characters, because these special characters does not need to be escaped
// in XML while in java URI they need to be escaped
try {
java.net.URI.create (mUserIdValue);
} catch (Exception ex) {
return false;
}
return true;
}
private boolean validateAlias () {
return ( (mUserIdValue != null) && (mUserIdValue.length() > 0));
}
private boolean validateOtherType () {
return ( (mOtherType != null) && (mOtherType.length() > 0) &&
(mUserIdValue != null) && (mUserIdValue.length() > 0) );
}
///@endcond
}