19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.text.util; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19adc6b850729635ea494c58c4f422b5defe96b95fScott Kennedyimport android.annotation.Nullable; 20adc6b850729635ea494c58c4f422b5defe96b95fScott Kennedy 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class stores an RFC 822-like name, address, and comment, 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and provides methods to convert them to quoted strings. 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Rfc822Token { 26adc6b850729635ea494c58c4f422b5defe96b95fScott Kennedy @Nullable 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private String mName, mAddress, mComment; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a new Rfc822Token with the specified name, address, 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and comment. 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 33adc6b850729635ea494c58c4f422b5defe96b95fScott Kennedy public Rfc822Token(@Nullable String name, @Nullable String address, @Nullable String comment) { 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = name; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAddress = address; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mComment = comment; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the name part. 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 42adc6b850729635ea494c58c4f422b5defe96b95fScott Kennedy @Nullable 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getName() { 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mName; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the address part. 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 50adc6b850729635ea494c58c4f422b5defe96b95fScott Kennedy @Nullable 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getAddress() { 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAddress; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the comment part. 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 58adc6b850729635ea494c58c4f422b5defe96b95fScott Kennedy @Nullable 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String getComment() { 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mComment; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Changes the name to the specified name. 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 66adc6b850729635ea494c58c4f422b5defe96b95fScott Kennedy public void setName(@Nullable String name) { 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mName = name; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Changes the address to the specified address. 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 73adc6b850729635ea494c58c4f422b5defe96b95fScott Kennedy public void setAddress(@Nullable String address) { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAddress = address; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Changes the comment to the specified comment. 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 80adc6b850729635ea494c58c4f422b5defe96b95fScott Kennedy public void setComment(@Nullable String comment) { 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mComment = comment; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the name (with quoting added if necessary), 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the comment (in parentheses), and the address (in angle brackets). 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This should be suitable for inclusion in an RFC 822 address list. 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mName != null && mName.length() != 0) { 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(quoteNameIfNecessary(mName)); 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(' '); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mComment != null && mComment.length() != 0) { 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append('('); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(quoteComment(mComment)); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(") "); 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAddress != null && mAddress.length() != 0) { 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append('<'); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(mAddress); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append('>'); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the name, conservatively quoting it if there are any 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * characters that are likely to cause trouble outside of a 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * quoted string, or returning it literally if it seems safe. 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String quoteNameIfNecessary(String name) { 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = name.length(); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < len; i++) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = name.charAt(i); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 123f26c6617a91f25ed1178d01de4108cf6f54f910cTadashi Takaoka if (! ((c >= 'A' && c <= 'Z') || 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (c >= 'a' && c <= 'z') || 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (c == ' ') || 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (c >= '0' && c <= '9'))) { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return '"' + quoteName(name) + '"'; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return name; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the name, with internal backslashes and quotation marks 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * preceded by backslashes. The outer quote marks themselves are not 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * added by this method. 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String quoteName(String name) { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = name.length(); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < len; i++) { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = name.charAt(i); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == '\\' || c == '"') { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append('\\'); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(c); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the comment, with internal backslashes and parentheses 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * preceded by backslashes. The outer parentheses themselves are 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not added by this method. 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static String quoteComment(String comment) { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = comment.length(); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project StringBuilder sb = new StringBuilder(); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < len; i++) { 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = comment.charAt(i); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c == '(' || c == ')' || c == '\\') { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append('\\'); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sb.append(c); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sb.toString(); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17778a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh 17878a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh public int hashCode() { 17978a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh int result = 17; 18078a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh if (mName != null) result = 31 * result + mName.hashCode(); 18178a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh if (mAddress != null) result = 31 * result + mAddress.hashCode(); 18278a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh if (mComment != null) result = 31 * result + mComment.hashCode(); 18378a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh return result; 18478a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh } 18578a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh 18678a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh private static boolean stringEquals(String a, String b) { 18778a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh if (a == null) { 18878a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh return (b == null); 18978a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh } else { 19078a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh return (a.equals(b)); 19178a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh } 19278a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh } 19378a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh 19478a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh public boolean equals(Object o) { 19578a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh if (!(o instanceof Rfc822Token)) { 19678a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh return false; 19778a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh } 19878a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh Rfc822Token other = (Rfc822Token) o; 19978a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh return (stringEquals(mName, other.mName) && 20078a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh stringEquals(mAddress, other.mAddress) && 20178a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh stringEquals(mComment, other.mComment)); 20278a5b8106a4768f7a67e5a29c58f23cd95f6c47cDebajit Ghosh } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 205