001    /****************************************************************
002     * Licensed to the Apache Software Foundation (ASF) under one   *
003     * or more contributor license agreements.  See the NOTICE file *
004     * distributed with this work for additional information        *
005     * regarding copyright ownership.  The ASF licenses this file   *
006     * to you under the Apache License, Version 2.0 (the            *
007     * "License"); you may not use this file except in compliance   *
008     * with the License.  You may obtain a copy of the License at   *
009     *                                                              *
010     *   http://www.apache.org/licenses/LICENSE-2.0                 *
011     *                                                              *
012     * Unless required by applicable law or agreed to in writing,   *
013     * software distributed under the License is distributed on an  *
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015     * KIND, either express or implied.  See the License for the    *
016     * specific language governing permissions and limitations      *
017     * under the License.                                           *
018     ****************************************************************/
019    
020    package org.apache.james.mime4j.field.address;
021    
022    import org.apache.james.mime4j.codec.EncoderUtil;
023    import org.apache.james.mime4j.dom.address.Address;
024    import org.apache.james.mime4j.dom.address.Group;
025    import org.apache.james.mime4j.dom.address.Mailbox;
026    
027    /**
028     * Default formatter for {@link Address} and its subclasses.
029     */
030    public class AddressFormatter {
031    
032        public static final AddressFormatter DEFAULT = new AddressFormatter();
033    
034        protected AddressFormatter() {
035            super();
036        }
037    
038        /**
039         * Formats the address as a human readable string, not including the route.
040         * The resulting string is intended for display purposes only and cannot be
041         * used for transport purposes.
042         *
043         * For example, if the unparsed address was
044         *
045         * <"Joe Cheng"@joecheng.com>
046         *
047         * this method would return
048         *
049         * <Joe Cheng@joecheng.com>
050         *
051         * which is not valid for transport; the local part would need to be
052         * re-quoted.
053         *
054         * @param includeRoute
055         *            <code>true</code> if the route should be included if it
056         *            exists, <code>false</code> otherwise.
057         */
058        public void format(final StringBuilder sb, final Address address, boolean includeRoute) {
059            if (address == null) {
060                return;
061            }
062            if (address instanceof Mailbox) {
063                format(sb, (Mailbox) address, includeRoute);
064            } else if (address instanceof Group) {
065                format(sb, (Group) address, includeRoute);
066            } else {
067                throw new IllegalArgumentException("Unsuppported Address class: " + address.getClass());
068            }
069        }
070    
071        /**
072         * Returns a string representation of this address that can be used for
073         * transport purposes. The route is never included in this representation
074         * because routes are obsolete and RFC 5322 states that obsolete syntactic
075         * forms MUST NOT be generated.
076         */
077        public void encode(final StringBuilder sb, final Address address) {
078            if (address == null) {
079                return;
080            }
081            if (address instanceof Mailbox) {
082                encode(sb, (Mailbox) address);
083            } else if (address instanceof Group) {
084                encode(sb, (Group) address);
085            } else {
086                throw new IllegalArgumentException("Unsuppported Address class: " + address.getClass());
087            }
088        }
089    
090        public void format(final StringBuilder sb, final Mailbox mailbox, boolean includeRoute) {
091            if (sb == null) {
092                throw new IllegalArgumentException("StringBuilder may not be null");
093            }
094            if (mailbox == null) {
095                throw new IllegalArgumentException("Mailbox may not be null");
096            }
097            includeRoute &= mailbox.getRoute() != null;
098            boolean includeAngleBrackets = mailbox.getName() != null || includeRoute;
099            if (mailbox.getName() != null) {
100                sb.append(mailbox.getName());
101                sb.append(' ');
102            }
103            if (includeAngleBrackets) {
104                sb.append('<');
105            }
106            if (includeRoute) {
107                sb.append(mailbox.getRoute().toRouteString());
108                sb.append(':');
109            }
110            sb.append(mailbox.getLocalPart());
111            if (mailbox.getDomain() != null) {
112                sb.append('@');
113                sb.append(mailbox.getDomain());
114            }
115            if (includeAngleBrackets) {
116                sb.append('>');
117            }
118        }
119    
120        public String format(final Mailbox mailbox, boolean includeRoute) {
121            StringBuilder sb = new StringBuilder();
122            format(sb, mailbox, includeRoute);
123            return sb.toString();
124        }
125    
126        public void encode(final StringBuilder sb, final Mailbox mailbox) {
127            if (sb == null) {
128                throw new IllegalArgumentException("StringBuilder may not be null");
129            }
130            if (mailbox == null) {
131                throw new IllegalArgumentException("Mailbox may not be null");
132            }
133            if (mailbox.getName() != null) {
134                sb.append(EncoderUtil.encodeAddressDisplayName(mailbox.getName()));
135                sb.append(" <");
136            }
137            sb.append(EncoderUtil.encodeAddressLocalPart(mailbox.getLocalPart()));
138            // domain = dot-atom / domain-literal
139            // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
140            // dtext = %d33-90 / %d94-126
141            if (mailbox.getDomain() != null) {
142                sb.append('@');
143                sb.append(mailbox.getDomain());
144            }
145            if (mailbox.getName() != null) {
146                sb.append('>');
147            }
148        }
149    
150        public String encode(final Mailbox mailbox) {
151            StringBuilder sb = new StringBuilder();
152            encode(sb, mailbox);
153            return sb.toString();
154        }
155    
156        public void format(final StringBuilder sb, final Group group, boolean includeRoute) {
157            if (sb == null) {
158                throw new IllegalArgumentException("StringBuilder may not be null");
159            }
160            if (group == null) {
161                throw new IllegalArgumentException("Group may not be null");
162            }
163            sb.append(group.getName());
164            sb.append(':');
165    
166            boolean first = true;
167            for (Mailbox mailbox : group.getMailboxes()) {
168                if (first) {
169                    first = false;
170                } else {
171                    sb.append(',');
172                }
173                sb.append(' ');
174                format(sb, mailbox, includeRoute);
175            }
176            sb.append(";");
177        }
178    
179        public String format(final Group group, boolean includeRoute) {
180            StringBuilder sb = new StringBuilder();
181            format(sb, group, includeRoute);
182            return sb.toString();
183        }
184    
185        public void encode(final StringBuilder sb, final Group group) {
186            if (sb == null) {
187                throw new IllegalArgumentException("StringBuilder may not be null");
188            }
189            if (group == null) {
190                throw new IllegalArgumentException("Group may not be null");
191            }
192            sb.append(EncoderUtil.encodeAddressDisplayName(group.getName()));
193            sb.append(':');
194            boolean first = true;
195            for (Mailbox mailbox : group.getMailboxes()) {
196                if (first) {
197                    first = false;
198                } else {
199                    sb.append(',');
200                }
201    
202                sb.append(' ');
203                encode(sb, mailbox);
204            }
205            sb.append(';');
206        }
207    
208        public String encode(final Group group) {
209            StringBuilder sb = new StringBuilder();
210            encode(sb, group);
211            return sb.toString();
212        }
213    
214    }