Builder.java revision 8978aac1977408b05e386ae846c30920c7faa0a6
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 20package org.apache.james.mime4j.field.address; 21 22import java.util.ArrayList; 23import java.util.Iterator; 24 25import org.apache.james.mime4j.decoder.DecoderUtil; 26import org.apache.james.mime4j.field.address.parser.*; 27import org.apache.james.mime4j.field.address.parser.ASTaddr_spec; 28import org.apache.james.mime4j.field.address.parser.ASTaddress; 29import org.apache.james.mime4j.field.address.parser.ASTaddress_list; 30import org.apache.james.mime4j.field.address.parser.ASTangle_addr; 31import org.apache.james.mime4j.field.address.parser.ASTdomain; 32import org.apache.james.mime4j.field.address.parser.ASTgroup_body; 33import org.apache.james.mime4j.field.address.parser.ASTlocal_part; 34import org.apache.james.mime4j.field.address.parser.ASTmailbox; 35import org.apache.james.mime4j.field.address.parser.ASTname_addr; 36import org.apache.james.mime4j.field.address.parser.ASTphrase; 37import org.apache.james.mime4j.field.address.parser.ASTroute; 38import org.apache.james.mime4j.field.address.parser.Node; 39import org.apache.james.mime4j.field.address.parser.SimpleNode; 40import org.apache.james.mime4j.field.address.parser.Token; 41 42/** 43 * Transforms the JJTree-generated abstract syntax tree 44 * into a graph of org.apache.james.mime4j.field.address objects. 45 * 46 * 47 */ 48class Builder { 49 50 private static Builder singleton = new Builder(); 51 52 public static Builder getInstance() { 53 return singleton; 54 } 55 56 57 58 public AddressList buildAddressList(ASTaddress_list node) { 59 ArrayList list = new ArrayList(); 60 for (int i = 0; i < node.jjtGetNumChildren(); i++) { 61 ASTaddress childNode = (ASTaddress) node.jjtGetChild(i); 62 Address address = buildAddress(childNode); 63 list.add(address); 64 } 65 return new AddressList(list, true); 66 } 67 68 private Address buildAddress(ASTaddress node) { 69 ChildNodeIterator it = new ChildNodeIterator(node); 70 Node n = it.nextNode(); 71 if (n instanceof ASTaddr_spec) { 72 return buildAddrSpec((ASTaddr_spec)n); 73 } 74 else if (n instanceof ASTangle_addr) { 75 return buildAngleAddr((ASTangle_addr)n); 76 } 77 else if (n instanceof ASTphrase) { 78 String name = buildString((ASTphrase)n, false); 79 Node n2 = it.nextNode(); 80 if (n2 instanceof ASTgroup_body) { 81 return new Group(name, buildGroupBody((ASTgroup_body)n2)); 82 } 83 else if (n2 instanceof ASTangle_addr) { 84 name = DecoderUtil.decodeEncodedWords(name); 85 return new NamedMailbox(name, buildAngleAddr((ASTangle_addr)n2)); 86 } 87 else { 88 throw new IllegalStateException(); 89 } 90 } 91 else { 92 throw new IllegalStateException(); 93 } 94 } 95 96 97 98 private MailboxList buildGroupBody(ASTgroup_body node) { 99 ArrayList results = new ArrayList(); 100 ChildNodeIterator it = new ChildNodeIterator(node); 101 while (it.hasNext()) { 102 Node n = it.nextNode(); 103 if (n instanceof ASTmailbox) 104 results.add(buildMailbox((ASTmailbox)n)); 105 else 106 throw new IllegalStateException(); 107 } 108 return new MailboxList(results, true); 109 } 110 111 private Mailbox buildMailbox(ASTmailbox node) { 112 ChildNodeIterator it = new ChildNodeIterator(node); 113 Node n = it.nextNode(); 114 if (n instanceof ASTaddr_spec) { 115 return buildAddrSpec((ASTaddr_spec)n); 116 } 117 else if (n instanceof ASTangle_addr) { 118 return buildAngleAddr((ASTangle_addr)n); 119 } 120 else if (n instanceof ASTname_addr) { 121 return buildNameAddr((ASTname_addr)n); 122 } 123 else { 124 throw new IllegalStateException(); 125 } 126 } 127 128 private NamedMailbox buildNameAddr(ASTname_addr node) { 129 ChildNodeIterator it = new ChildNodeIterator(node); 130 Node n = it.nextNode(); 131 String name; 132 if (n instanceof ASTphrase) { 133 name = buildString((ASTphrase)n, false); 134 } 135 else { 136 throw new IllegalStateException(); 137 } 138 139 n = it.nextNode(); 140 if (n instanceof ASTangle_addr) { 141 name = DecoderUtil.decodeEncodedWords(name); 142 return new NamedMailbox(name, buildAngleAddr((ASTangle_addr) n)); 143 } 144 else { 145 throw new IllegalStateException(); 146 } 147 } 148 149 private Mailbox buildAngleAddr(ASTangle_addr node) { 150 ChildNodeIterator it = new ChildNodeIterator(node); 151 DomainList route = null; 152 Node n = it.nextNode(); 153 if (n instanceof ASTroute) { 154 route = buildRoute((ASTroute)n); 155 n = it.nextNode(); 156 } 157 else if (n instanceof ASTaddr_spec) 158 ; // do nothing 159 else 160 throw new IllegalStateException(); 161 162 if (n instanceof ASTaddr_spec) 163 return buildAddrSpec(route, (ASTaddr_spec)n); 164 else 165 throw new IllegalStateException(); 166 } 167 168 private DomainList buildRoute(ASTroute node) { 169 ArrayList results = new ArrayList(node.jjtGetNumChildren()); 170 ChildNodeIterator it = new ChildNodeIterator(node); 171 while (it.hasNext()) { 172 Node n = it.nextNode(); 173 if (n instanceof ASTdomain) 174 results.add(buildString((ASTdomain)n, true)); 175 else 176 throw new IllegalStateException(); 177 } 178 return new DomainList(results, true); 179 } 180 181 private Mailbox buildAddrSpec(ASTaddr_spec node) { 182 return buildAddrSpec(null, node); 183 } 184 private Mailbox buildAddrSpec(DomainList route, ASTaddr_spec node) { 185 ChildNodeIterator it = new ChildNodeIterator(node); 186 String localPart = buildString((ASTlocal_part)it.nextNode(), true); 187 String domain = buildString((ASTdomain)it.nextNode(), true); 188 return new Mailbox(route, localPart, domain); 189 } 190 191 192 private String buildString(SimpleNode node, boolean stripSpaces) { 193 Token head = node.firstToken; 194 Token tail = node.lastToken; 195 StringBuffer out = new StringBuffer(); 196 197 while (head != tail) { 198 out.append(head.image); 199 head = head.next; 200 if (!stripSpaces) 201 addSpecials(out, head.specialToken); 202 } 203 out.append(tail.image); 204 205 return out.toString(); 206 } 207 208 private void addSpecials(StringBuffer out, Token specialToken) { 209 if (specialToken != null) { 210 addSpecials(out, specialToken.specialToken); 211 out.append(specialToken.image); 212 } 213 } 214 215 private static class ChildNodeIterator implements Iterator { 216 217 private SimpleNode simpleNode; 218 private int index; 219 private int len; 220 221 public ChildNodeIterator(SimpleNode simpleNode) { 222 this.simpleNode = simpleNode; 223 this.len = simpleNode.jjtGetNumChildren(); 224 this.index = 0; 225 } 226 227 public void remove() { 228 throw new UnsupportedOperationException(); 229 } 230 231 public boolean hasNext() { 232 return index < len; 233 } 234 235 public Object next() { 236 return nextNode(); 237 } 238 239 public Node nextNode() { 240 return simpleNode.jjtGetChild(index++); 241 } 242 243 } 244} 245