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
17package android.text.util;
18
19/**
20 * This class stores an RFC 822-like name, address, and comment,
21 * and provides methods to convert them to quoted strings.
22 */
23public class Rfc822Token {
24    private String mName, mAddress, mComment;
25
26    /**
27     * Creates a new Rfc822Token with the specified name, address,
28     * and comment.
29     */
30    public Rfc822Token(String name, String address, String comment) {
31        mName = name;
32        mAddress = address;
33        mComment = comment;
34    }
35
36    /**
37     * Returns the name part.
38     */
39    public String getName() {
40        return mName;
41    }
42
43    /**
44     * Returns the address part.
45     */
46    public String getAddress() {
47        return mAddress;
48    }
49
50    /**
51     * Returns the comment part.
52     */
53    public String getComment() {
54        return mComment;
55    }
56
57    /**
58     * Changes the name to the specified name.
59     */
60    public void setName(String name) {
61        mName = name;
62    }
63
64    /**
65     * Changes the address to the specified address.
66     */
67    public void setAddress(String address) {
68        mAddress = address;
69    }
70
71    /**
72     * Changes the comment to the specified comment.
73     */
74    public void setComment(String comment) {
75        mComment = comment;
76    }
77
78    /**
79     * Returns the name (with quoting added if necessary),
80     * the comment (in parentheses), and the address (in angle brackets).
81     * This should be suitable for inclusion in an RFC 822 address list.
82     */
83    public String toString() {
84        StringBuilder sb = new StringBuilder();
85
86        if (mName != null && mName.length() != 0) {
87            sb.append(quoteNameIfNecessary(mName));
88            sb.append(' ');
89        }
90
91        if (mComment != null && mComment.length() != 0) {
92            sb.append('(');
93            sb.append(quoteComment(mComment));
94            sb.append(") ");
95        }
96
97        if (mAddress != null && mAddress.length() != 0) {
98            sb.append('<');
99            sb.append(mAddress);
100            sb.append('>');
101        }
102
103        return sb.toString();
104    }
105
106    /**
107     * Returns the name, conservatively quoting it if there are any
108     * characters that are likely to cause trouble outside of a
109     * quoted string, or returning it literally if it seems safe.
110     */
111    public static String quoteNameIfNecessary(String name) {
112        int len = name.length();
113
114        for (int i = 0; i < len; i++) {
115            char c = name.charAt(i);
116
117            if (! ((c >= 'A' && c <= 'Z') ||
118                   (c >= 'a' && c <= 'z') ||
119                   (c == ' ') ||
120                   (c >= '0' && c <= '9'))) {
121                return '"' + quoteName(name) + '"';
122            }
123        }
124
125        return name;
126    }
127
128    /**
129     * Returns the name, with internal backslashes and quotation marks
130     * preceded by backslashes.  The outer quote marks themselves are not
131     * added by this method.
132     */
133    public static String quoteName(String name) {
134        StringBuilder sb = new StringBuilder();
135
136        int len = name.length();
137        for (int i = 0; i < len; i++) {
138            char c = name.charAt(i);
139
140            if (c == '\\' || c == '"') {
141                sb.append('\\');
142            }
143
144            sb.append(c);
145        }
146
147        return sb.toString();
148    }
149
150    /**
151     * Returns the comment, with internal backslashes and parentheses
152     * preceded by backslashes.  The outer parentheses themselves are
153     * not added by this method.
154     */
155    public static String quoteComment(String comment) {
156        int len = comment.length();
157        StringBuilder sb = new StringBuilder();
158
159        for (int i = 0; i < len; i++) {
160            char c = comment.charAt(i);
161
162            if (c == '(' || c == ')' || c == '\\') {
163                sb.append('\\');
164            }
165
166            sb.append(c);
167        }
168
169        return sb.toString();
170    }
171
172    public int hashCode() {
173        int result = 17;
174        if (mName != null) result = 31 * result + mName.hashCode();
175        if (mAddress != null) result = 31 * result + mAddress.hashCode();
176        if (mComment != null) result = 31 * result + mComment.hashCode();
177        return result;
178    }
179
180    private static boolean stringEquals(String a, String b) {
181        if (a == null) {
182            return (b == null);
183        } else {
184            return (a.equals(b));
185        }
186    }
187
188    public boolean equals(Object o) {
189        if (!(o instanceof Rfc822Token)) {
190            return false;
191        }
192        Rfc822Token other = (Rfc822Token) o;
193        return (stringEquals(mName, other.mName) &&
194                stringEquals(mAddress, other.mAddress) &&
195                stringEquals(mComment, other.mComment));
196    }
197}
198
199