1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.text.util; 18 19 import android.annotation.Nullable; 20 21 /** 22 * This class stores an RFC 822-like name, address, and comment, 23 * and provides methods to convert them to quoted strings. 24 */ 25 public class Rfc822Token { 26 @Nullable 27 private String mName, mAddress, mComment; 28 29 /** 30 * Creates a new Rfc822Token with the specified name, address, 31 * and comment. 32 */ Rfc822Token(@ullable String name, @Nullable String address, @Nullable String comment)33 public Rfc822Token(@Nullable String name, @Nullable String address, @Nullable String comment) { 34 mName = name; 35 mAddress = address; 36 mComment = comment; 37 } 38 39 /** 40 * Returns the name part. 41 */ 42 @Nullable getName()43 public String getName() { 44 return mName; 45 } 46 47 /** 48 * Returns the address part. 49 */ 50 @Nullable getAddress()51 public String getAddress() { 52 return mAddress; 53 } 54 55 /** 56 * Returns the comment part. 57 */ 58 @Nullable getComment()59 public String getComment() { 60 return mComment; 61 } 62 63 /** 64 * Changes the name to the specified name. 65 */ setName(@ullable String name)66 public void setName(@Nullable String name) { 67 mName = name; 68 } 69 70 /** 71 * Changes the address to the specified address. 72 */ setAddress(@ullable String address)73 public void setAddress(@Nullable String address) { 74 mAddress = address; 75 } 76 77 /** 78 * Changes the comment to the specified comment. 79 */ setComment(@ullable String comment)80 public void setComment(@Nullable String comment) { 81 mComment = comment; 82 } 83 84 /** 85 * Returns the name (with quoting added if necessary), 86 * the comment (in parentheses), and the address (in angle brackets). 87 * This should be suitable for inclusion in an RFC 822 address list. 88 */ toString()89 public String toString() { 90 StringBuilder sb = new StringBuilder(); 91 92 if (mName != null && mName.length() != 0) { 93 sb.append(quoteNameIfNecessary(mName)); 94 sb.append(' '); 95 } 96 97 if (mComment != null && mComment.length() != 0) { 98 sb.append('('); 99 sb.append(quoteComment(mComment)); 100 sb.append(") "); 101 } 102 103 if (mAddress != null && mAddress.length() != 0) { 104 sb.append('<'); 105 sb.append(mAddress); 106 sb.append('>'); 107 } 108 109 return sb.toString(); 110 } 111 112 /** 113 * Returns the name, conservatively quoting it if there are any 114 * characters that are likely to cause trouble outside of a 115 * quoted string, or returning it literally if it seems safe. 116 */ quoteNameIfNecessary(String name)117 public static String quoteNameIfNecessary(String name) { 118 int len = name.length(); 119 120 for (int i = 0; i < len; i++) { 121 char c = name.charAt(i); 122 123 if (! ((c >= 'A' && c <= 'Z') || 124 (c >= 'a' && c <= 'z') || 125 (c == ' ') || 126 (c >= '0' && c <= '9'))) { 127 return '"' + quoteName(name) + '"'; 128 } 129 } 130 131 return name; 132 } 133 134 /** 135 * Returns the name, with internal backslashes and quotation marks 136 * preceded by backslashes. The outer quote marks themselves are not 137 * added by this method. 138 */ quoteName(String name)139 public static String quoteName(String name) { 140 StringBuilder sb = new StringBuilder(); 141 142 int len = name.length(); 143 for (int i = 0; i < len; i++) { 144 char c = name.charAt(i); 145 146 if (c == '\\' || c == '"') { 147 sb.append('\\'); 148 } 149 150 sb.append(c); 151 } 152 153 return sb.toString(); 154 } 155 156 /** 157 * Returns the comment, with internal backslashes and parentheses 158 * preceded by backslashes. The outer parentheses themselves are 159 * not added by this method. 160 */ quoteComment(String comment)161 public static String quoteComment(String comment) { 162 int len = comment.length(); 163 StringBuilder sb = new StringBuilder(); 164 165 for (int i = 0; i < len; i++) { 166 char c = comment.charAt(i); 167 168 if (c == '(' || c == ')' || c == '\\') { 169 sb.append('\\'); 170 } 171 172 sb.append(c); 173 } 174 175 return sb.toString(); 176 } 177 hashCode()178 public int hashCode() { 179 int result = 17; 180 if (mName != null) result = 31 * result + mName.hashCode(); 181 if (mAddress != null) result = 31 * result + mAddress.hashCode(); 182 if (mComment != null) result = 31 * result + mComment.hashCode(); 183 return result; 184 } 185 stringEquals(String a, String b)186 private static boolean stringEquals(String a, String b) { 187 if (a == null) { 188 return (b == null); 189 } else { 190 return (a.equals(b)); 191 } 192 } 193 equals(Object o)194 public boolean equals(Object o) { 195 if (!(o instanceof Rfc822Token)) { 196 return false; 197 } 198 Rfc822Token other = (Rfc822Token) o; 199 return (stringEquals(mName, other.mName) && 200 stringEquals(mAddress, other.mAddress) && 201 stringEquals(mComment, other.mComment)); 202 } 203 } 204 205