/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.im.imps;
import android.os.Parcel;
import com.android.im.engine.Address;
import com.android.im.engine.ImEntity;
/**
* The abstract representation of an IMPS address.
*/
public abstract class ImpsAddress extends Address {
private static final char[] SPECIALS = {'/', '@', '+'};
protected String mUser;
protected String mResource;
protected String mDomain;
private String mFullAddress;
protected ImpsAddress() {
}
protected ImpsAddress(String user, String resource, String domain) {
// build the full address and unify the fields to lower case since imps
// address is case insensitive.
StringBuilder buf = new StringBuilder(ImpsConstants.ADDRESS_PREFIX);
if(user != null) {
buf.append(user.toLowerCase());
}
if(resource != null) {
buf.append('/').append(resource.toLowerCase());
}
if(domain != null) {
buf.append('@').append(domain.toLowerCase());
}
mFullAddress = buf.toString();
mUser = user;
mResource = resource;
mDomain = domain;
verifyAddress();
}
protected ImpsAddress(String full){
this(full, true);
}
protected ImpsAddress(String full, boolean verify) {
if (full == null || full.length() == 0) {
throw new IllegalArgumentException();
}
//TODO: escape reserved characters.
if(!full.startsWith(ImpsConstants.ADDRESS_PREFIX)) {
full = ImpsConstants.ADDRESS_PREFIX + full;
}
parse(full);
mFullAddress = full;
if (verify) {
verifyAddress();
}
}
private void parse(String full) {
mUser = parseUser(full);
mResource = parseResource(full);
mDomain = parseDomain(full);
}
private void verifyAddress() throws IllegalArgumentException {
ImpsLog.log("verifyAddress:" + mUser + ", " + mResource + ", " + mDomain);
if(mUser == null && mResource == null) {
throw new IllegalArgumentException();
}
if(mUser != null) {
if(mUser.length() == 0) {
throw new IllegalArgumentException("Invalid user");
}
if(mUser.charAt(0) == '+') {//mobile number
for(int i = 1; i < mUser.length(); i++) {
if(!Character.isDigit(mUser.charAt(i))) {
throw new IllegalArgumentException("Invalid user");
}
}
} else if(!isAlphaSequence(mUser)) {
throw new IllegalArgumentException("Invalid user");
}
}
if(mResource != null && !isAlphaSequence(mResource)) {
throw new IllegalArgumentException("Invalid resource");
}
if(mDomain != null && !isAlphaSequence(mDomain)) {
throw new IllegalArgumentException("Invalid domain");
}
}
/**
* Gets the User-part of the address which refers to the identification of
* the IMPS user.
*
* @return the User-part of the address.
*/
public String getUser() {
return mUser;
}
/**
* Gets the Resource-part of the address which identifies the referred
* public or private resource.
*
* @return the Resource-part of the address.
*/
public String getResource() {
return mResource;
}
/**
* Gets the Domain-part of the address which identifies the IMPS server
* domain.
*
* @return the Domain-part of the address.
*/
public String getDomain() {
return mDomain;
}
/**
* Gets the full string representation of the address.
*/
@Override
public String getFullName() {
return mFullAddress;
}
@Override
public void writeToParcel(Parcel dest) {
dest.writeString(mFullAddress);
}
@Override
public void readFromParcel(Parcel source) {
mFullAddress = source.readString();
parse(mFullAddress);
}
@Override
public boolean equals(Object other) {
return other instanceof ImpsAddress
&& mFullAddress.equalsIgnoreCase(((ImpsAddress)other).mFullAddress);
}
@Override
public int hashCode() {
return mFullAddress.toLowerCase().hashCode();
}
/**
* Formats the address to a PrimitiveElement which can be used as the
* content of Sender or Recipient.
*
* @return a PrimitiveElement.
*/
public abstract PrimitiveElement toPrimitiveElement();
/**
* Gets the entity this address object refers to.
*
* @param connection
* @return the entity this address refers to or <code>null</code> if the
* entity not found.
*/
abstract ImEntity getEntity(ImpsConnection connection);
/**
* Constructs an ImpsAddress from the Sender or Recipient element in a
* primitive.
*
* @param elem the Sender of Recipient element.
* @return the ImpsAddress object or <code>null</code> if it's not a valid
* element.
*/
public static ImpsAddress fromPrimitiveElement(PrimitiveElement elem) {
String type = elem.getTagName();
if(ImpsTags.User.equals(type)) {
return new ImpsUserAddress(elem.getChildContents(ImpsTags.UserID), false);
} else if(ImpsTags.Group.equals(type)) {
PrimitiveElement child = elem.getFirstChild();
if(child == null) {
throw new IllegalArgumentException();
}
if(ImpsTags.GroupID.equals(child.getTagName())){
return new ImpsGroupAddress(child.getContents());
} else {
String screeName = child.getChildContents(ImpsTags.SName);
String groupId = child.getChildContents(ImpsTags.GroupID);
return new ImpsGroupAddress(groupId, screeName);
}
} else if(ImpsTags.ContactList.equals(type)) {
return new ImpsContactListAddress(elem.getContents(), false);
} else {
throw new IllegalArgumentException();
}
}
private String parseUser(String full) {
int index = full.indexOf('/');
if(index == 3) {
return null;
}
if (index == -1) {
index = full.lastIndexOf('@');
}
if (index == -1) {
index = full.length();
}
return full.substring(3, index);
}
private String parseResource(String full) {
int beginIndex = full.indexOf('/');
if (beginIndex == -1) {
return null;
}
int endIndex = full.lastIndexOf('@');
if (endIndex == -1 || endIndex < beginIndex) {
endIndex = full.length();
}
return full.substring(beginIndex + 1, endIndex);
}
private String parseDomain(String full) {
int beginIndex = full.lastIndexOf('@');
return beginIndex == -1 ? null : full.substring(beginIndex + 1);
}
private boolean isAlphaSequence(String str) {
for(int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if(ch < 32 || ch > 126 || isSpecial(ch)) {
return false;
}
}
return true;
}
private boolean isSpecial(char ch) {
for (char element : SPECIALS) {
if(ch == element) {
return true;
}
}
return false;
}
}
|