• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one   *
3  * or more contributor license agreements.  See the NOTICE file *
4  * distributed with this work for additional information        *
5  * regarding copyright ownership.  The ASF licenses this file   *
6  * to you under the Apache License, Version 2.0 (the            *
7  * "License"); you may not use this file except in compliance   *
8  * with the License.  You may obtain a copy of the License at   *
9  *                                                              *
10  *   http://www.apache.org/licenses/LICENSE-2.0                 *
11  *                                                              *
12  * Unless required by applicable law or agreed to in writing,   *
13  * software distributed under the License is distributed on an  *
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15  * KIND, either express or implied.  See the License for the    *
16  * specific language governing permissions and limitations      *
17  * under the License.                                           *
18  ****************************************************************/
19 
20 package org.apache.james.mime4j.field.address;
21 
22 import java.util.ArrayList;
23 import java.util.Iterator;
24 
25 import org.apache.james.mime4j.decoder.DecoderUtil;
26 import org.apache.james.mime4j.field.address.parser.ASTaddr_spec;
27 import org.apache.james.mime4j.field.address.parser.ASTaddress;
28 import org.apache.james.mime4j.field.address.parser.ASTaddress_list;
29 import org.apache.james.mime4j.field.address.parser.ASTangle_addr;
30 import org.apache.james.mime4j.field.address.parser.ASTdomain;
31 import org.apache.james.mime4j.field.address.parser.ASTgroup_body;
32 import org.apache.james.mime4j.field.address.parser.ASTlocal_part;
33 import org.apache.james.mime4j.field.address.parser.ASTmailbox;
34 import org.apache.james.mime4j.field.address.parser.ASTname_addr;
35 import org.apache.james.mime4j.field.address.parser.ASTphrase;
36 import org.apache.james.mime4j.field.address.parser.ASTroute;
37 import org.apache.james.mime4j.field.address.parser.Node;
38 import org.apache.james.mime4j.field.address.parser.SimpleNode;
39 import org.apache.james.mime4j.field.address.parser.Token;
40 
41 /**
42  * Transforms the JJTree-generated abstract syntax tree
43  * into a graph of org.apache.james.mime4j.field.address objects.
44  *
45  *
46  */
47 class Builder {
48 
49 	private static Builder singleton = new Builder();
50 
getInstance()51 	public static Builder getInstance() {
52 		return singleton;
53 	}
54 
55 
56 
buildAddressList(ASTaddress_list node)57 	public AddressList buildAddressList(ASTaddress_list node) {
58 		ArrayList<Address> list = new ArrayList<Address>();
59 		for (int i = 0; i < node.jjtGetNumChildren(); i++) {
60 			ASTaddress childNode = (ASTaddress) node.jjtGetChild(i);
61 			Address address = buildAddress(childNode);
62 			list.add(address);
63 		}
64 		return new AddressList(list, true);
65 	}
66 
buildAddress(ASTaddress node)67 	private Address buildAddress(ASTaddress node) {
68 		ChildNodeIterator it = new ChildNodeIterator(node);
69 		Node n = it.nextNode();
70 		if (n instanceof ASTaddr_spec) {
71 			return buildAddrSpec((ASTaddr_spec)n);
72 		}
73 		else if (n instanceof ASTangle_addr) {
74 			return buildAngleAddr((ASTangle_addr)n);
75 		}
76 		else if (n instanceof ASTphrase) {
77 			String name = buildString((ASTphrase)n, false);
78 			Node n2 = it.nextNode();
79 			if (n2 instanceof ASTgroup_body) {
80 				return new Group(name, buildGroupBody((ASTgroup_body)n2));
81 			}
82 			else if (n2 instanceof ASTangle_addr) {
83                 name = DecoderUtil.decodeEncodedWords(name);
84 				return new NamedMailbox(name, buildAngleAddr((ASTangle_addr)n2));
85 			}
86 			else {
87 				throw new IllegalStateException();
88 			}
89 		}
90 		else {
91 			throw new IllegalStateException();
92 		}
93 	}
94 
95 
96 
buildGroupBody(ASTgroup_body node)97 	private MailboxList buildGroupBody(ASTgroup_body node) {
98 		ArrayList<Address> results = new ArrayList<Address>();
99 		ChildNodeIterator it = new ChildNodeIterator(node);
100 		while (it.hasNext()) {
101 			Node n = it.nextNode();
102 			if (n instanceof ASTmailbox)
103 				results.add(buildMailbox((ASTmailbox)n));
104 			else
105 				throw new IllegalStateException();
106 		}
107 		return new MailboxList(results, true);
108 	}
109 
buildMailbox(ASTmailbox node)110 	private Mailbox buildMailbox(ASTmailbox node) {
111 		ChildNodeIterator it = new ChildNodeIterator(node);
112 		Node n = it.nextNode();
113 		if (n instanceof ASTaddr_spec) {
114 			return buildAddrSpec((ASTaddr_spec)n);
115 		}
116 		else if (n instanceof ASTangle_addr) {
117 			return buildAngleAddr((ASTangle_addr)n);
118 		}
119 		else if (n instanceof ASTname_addr) {
120 			return buildNameAddr((ASTname_addr)n);
121 		}
122 		else {
123 			throw new IllegalStateException();
124 		}
125 	}
126 
buildNameAddr(ASTname_addr node)127 	private NamedMailbox buildNameAddr(ASTname_addr node) {
128 		ChildNodeIterator it = new ChildNodeIterator(node);
129 		Node n = it.nextNode();
130 		String name;
131 		if (n instanceof ASTphrase) {
132 			name = buildString((ASTphrase)n, false);
133 		}
134 		else {
135 			throw new IllegalStateException();
136 		}
137 
138 		n = it.nextNode();
139 		if (n instanceof ASTangle_addr) {
140             name = DecoderUtil.decodeEncodedWords(name);
141 			return new NamedMailbox(name, buildAngleAddr((ASTangle_addr) n));
142 		}
143 		else {
144 			throw new IllegalStateException();
145 		}
146 	}
147 
buildAngleAddr(ASTangle_addr node)148 	private Mailbox buildAngleAddr(ASTangle_addr node) {
149 		ChildNodeIterator it = new ChildNodeIterator(node);
150 		DomainList route = null;
151 		Node n = it.nextNode();
152 		if (n instanceof ASTroute) {
153 			route = buildRoute((ASTroute)n);
154 			n = it.nextNode();
155 		}
156 		else if (n instanceof ASTaddr_spec)
157 			; // do nothing
158 		else
159 			throw new IllegalStateException();
160 
161 		if (n instanceof ASTaddr_spec)
162 			return buildAddrSpec(route, (ASTaddr_spec)n);
163 		else
164 			throw new IllegalStateException();
165 	}
166 
buildRoute(ASTroute node)167 	private DomainList buildRoute(ASTroute node) {
168 		ArrayList<String> results = new ArrayList<String>(node.jjtGetNumChildren());
169 		ChildNodeIterator it = new ChildNodeIterator(node);
170 		while (it.hasNext()) {
171 			Node n = it.nextNode();
172 			if (n instanceof ASTdomain)
173 				results.add(buildString((ASTdomain)n, true));
174 			else
175 				throw new IllegalStateException();
176 		}
177 		return new DomainList(results, true);
178 	}
179 
buildAddrSpec(ASTaddr_spec node)180 	private Mailbox buildAddrSpec(ASTaddr_spec node) {
181 		return buildAddrSpec(null, node);
182 	}
buildAddrSpec(DomainList route, ASTaddr_spec node)183 	private Mailbox buildAddrSpec(DomainList route, ASTaddr_spec node) {
184 		ChildNodeIterator it = new ChildNodeIterator(node);
185 		String localPart = buildString((ASTlocal_part)it.nextNode(), true);
186 		String domain = buildString((ASTdomain)it.nextNode(), true);
187 		return new Mailbox(route, localPart, domain);
188 	}
189 
190 
buildString(SimpleNode node, boolean stripSpaces)191 	private String buildString(SimpleNode node, boolean stripSpaces) {
192 		Token head = node.firstToken;
193 		Token tail = node.lastToken;
194 		StringBuffer out = new StringBuffer();
195 
196 		while (head != tail) {
197 			out.append(head.image);
198 			head = head.next;
199 			if (!stripSpaces)
200 				addSpecials(out, head.specialToken);
201 		}
202 		out.append(tail.image);
203 
204 		return out.toString();
205 	}
206 
addSpecials(StringBuffer out, Token specialToken)207 	private void addSpecials(StringBuffer out, Token specialToken) {
208 		if (specialToken != null) {
209 			addSpecials(out, specialToken.specialToken);
210 			out.append(specialToken.image);
211 		}
212 	}
213 
214 	private static class ChildNodeIterator implements Iterator<Node> {
215 
216 		private SimpleNode simpleNode;
217 		private int index;
218 		private int len;
219 
ChildNodeIterator(SimpleNode simpleNode)220 		public ChildNodeIterator(SimpleNode simpleNode) {
221 			this.simpleNode = simpleNode;
222 			this.len = simpleNode.jjtGetNumChildren();
223 			this.index = 0;
224 		}
225 
remove()226 		public void remove() {
227 			throw new UnsupportedOperationException();
228 		}
229 
hasNext()230 		public boolean hasNext() {
231 			return index < len;
232 		}
233 
next()234 		public Node next() {
235 			return nextNode();
236 		}
237 
nextNode()238 		public Node nextNode() {
239 			return simpleNode.jjtGetChild(index++);
240 		}
241 
242 	}
243 }
244