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 020package org.apache.james.mime4j.field.address; 021 022import org.apache.james.mime4j.codec.EncoderUtil; 023import org.apache.james.mime4j.dom.address.Address; 024import org.apache.james.mime4j.dom.address.Group; 025import org.apache.james.mime4j.dom.address.Mailbox; 026 027/** 028 * Default formatter for {@link Address} and its subclasses. 029 */ 030public 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}