Home | History | Annotate | Download | only in address
      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 
     51 	public static Builder getInstance() {
     52 		return singleton;
     53 	}
     54 
     55 
     56 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    180 	private Mailbox buildAddrSpec(ASTaddr_spec node) {
    181 		return buildAddrSpec(null, node);
    182 	}
    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 
    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 
    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 
    220 		public ChildNodeIterator(SimpleNode simpleNode) {
    221 			this.simpleNode = simpleNode;
    222 			this.len = simpleNode.jjtGetNumChildren();
    223 			this.index = 0;
    224 		}
    225 
    226 		public void remove() {
    227 			throw new UnsupportedOperationException();
    228 		}
    229 
    230 		public boolean hasNext() {
    231 			return index < len;
    232 		}
    233 
    234 		public Node next() {
    235 			return nextNode();
    236 		}
    237 
    238 		public Node nextNode() {
    239 			return simpleNode.jjtGetChild(index++);
    240 		}
    241 
    242 	}
    243 }
    244