| /**************************************************************** |
| * Licensed to the Apache Software Foundation (ASF) under one * |
| * or more contributor license agreements. See the NOTICE file * |
| * distributed with this work for additional information * |
| * regarding copyright ownership. The ASF licenses this file * |
| * to you under the Apache License, Version 2.0 (the * |
| * "License"); you may not use this file except in compliance * |
| * with the License. You may obtain a copy of the License at * |
| * * |
| * http://www.apache.org/licenses/LICENSE-2.0 * |
| * * |
| * Unless required by applicable law or agreed to in writing, * |
| * software distributed under the License is distributed on an * |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * |
| * KIND, either express or implied. See the License for the * |
| * specific language governing permissions and limitations * |
| * under the License. * |
| ****************************************************************/ |
| |
| package org.apache.james.mime4j.field.address; |
| |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| |
| import org.apache.james.mime4j.decoder.DecoderUtil; |
| import org.apache.james.mime4j.field.address.parser.ASTaddr_spec; |
| import org.apache.james.mime4j.field.address.parser.ASTaddress; |
| import org.apache.james.mime4j.field.address.parser.ASTaddress_list; |
| import org.apache.james.mime4j.field.address.parser.ASTangle_addr; |
| import org.apache.james.mime4j.field.address.parser.ASTdomain; |
| import org.apache.james.mime4j.field.address.parser.ASTgroup_body; |
| import org.apache.james.mime4j.field.address.parser.ASTlocal_part; |
| import org.apache.james.mime4j.field.address.parser.ASTmailbox; |
| import org.apache.james.mime4j.field.address.parser.ASTname_addr; |
| import org.apache.james.mime4j.field.address.parser.ASTphrase; |
| import org.apache.james.mime4j.field.address.parser.ASTroute; |
| import org.apache.james.mime4j.field.address.parser.Node; |
| import org.apache.james.mime4j.field.address.parser.SimpleNode; |
| import org.apache.james.mime4j.field.address.parser.Token; |
| |
| /** |
| * Transforms the JJTree-generated abstract syntax tree |
| * into a graph of org.apache.james.mime4j.field.address objects. |
| * |
| * |
| */ |
| class Builder { |
| |
| private static Builder singleton = new Builder(); |
| |
| public static Builder getInstance() { |
| return singleton; |
| } |
| |
| |
| |
| public AddressList buildAddressList(ASTaddress_list node) { |
| ArrayList<Address> list = new ArrayList<Address>(); |
| for (int i = 0; i < node.jjtGetNumChildren(); i++) { |
| ASTaddress childNode = (ASTaddress) node.jjtGetChild(i); |
| Address address = buildAddress(childNode); |
| list.add(address); |
| } |
| return new AddressList(list, true); |
| } |
| |
| private Address buildAddress(ASTaddress node) { |
| ChildNodeIterator it = new ChildNodeIterator(node); |
| Node n = it.nextNode(); |
| if (n instanceof ASTaddr_spec) { |
| return buildAddrSpec((ASTaddr_spec)n); |
| } |
| else if (n instanceof ASTangle_addr) { |
| return buildAngleAddr((ASTangle_addr)n); |
| } |
| else if (n instanceof ASTphrase) { |
| String name = buildString((ASTphrase)n, false); |
| Node n2 = it.nextNode(); |
| if (n2 instanceof ASTgroup_body) { |
| return new Group(name, buildGroupBody((ASTgroup_body)n2)); |
| } |
| else if (n2 instanceof ASTangle_addr) { |
| name = DecoderUtil.decodeEncodedWords(name); |
| return new NamedMailbox(name, buildAngleAddr((ASTangle_addr)n2)); |
| } |
| else { |
| throw new IllegalStateException(); |
| } |
| } |
| else { |
| throw new IllegalStateException(); |
| } |
| } |
| |
| |
| |
| private MailboxList buildGroupBody(ASTgroup_body node) { |
| ArrayList<Address> results = new ArrayList<Address>(); |
| ChildNodeIterator it = new ChildNodeIterator(node); |
| while (it.hasNext()) { |
| Node n = it.nextNode(); |
| if (n instanceof ASTmailbox) |
| results.add(buildMailbox((ASTmailbox)n)); |
| else |
| throw new IllegalStateException(); |
| } |
| return new MailboxList(results, true); |
| } |
| |
| private Mailbox buildMailbox(ASTmailbox node) { |
| ChildNodeIterator it = new ChildNodeIterator(node); |
| Node n = it.nextNode(); |
| if (n instanceof ASTaddr_spec) { |
| return buildAddrSpec((ASTaddr_spec)n); |
| } |
| else if (n instanceof ASTangle_addr) { |
| return buildAngleAddr((ASTangle_addr)n); |
| } |
| else if (n instanceof ASTname_addr) { |
| return buildNameAddr((ASTname_addr)n); |
| } |
| else { |
| throw new IllegalStateException(); |
| } |
| } |
| |
| private NamedMailbox buildNameAddr(ASTname_addr node) { |
| ChildNodeIterator it = new ChildNodeIterator(node); |
| Node n = it.nextNode(); |
| String name; |
| if (n instanceof ASTphrase) { |
| name = buildString((ASTphrase)n, false); |
| } |
| else { |
| throw new IllegalStateException(); |
| } |
| |
| n = it.nextNode(); |
| if (n instanceof ASTangle_addr) { |
| name = DecoderUtil.decodeEncodedWords(name); |
| return new NamedMailbox(name, buildAngleAddr((ASTangle_addr) n)); |
| } |
| else { |
| throw new IllegalStateException(); |
| } |
| } |
| |
| private Mailbox buildAngleAddr(ASTangle_addr node) { |
| ChildNodeIterator it = new ChildNodeIterator(node); |
| DomainList route = null; |
| Node n = it.nextNode(); |
| if (n instanceof ASTroute) { |
| route = buildRoute((ASTroute)n); |
| n = it.nextNode(); |
| } |
| else if (n instanceof ASTaddr_spec) |
| ; // do nothing |
| else |
| throw new IllegalStateException(); |
| |
| if (n instanceof ASTaddr_spec) |
| return buildAddrSpec(route, (ASTaddr_spec)n); |
| else |
| throw new IllegalStateException(); |
| } |
| |
| private DomainList buildRoute(ASTroute node) { |
| ArrayList<String> results = new ArrayList<String>(node.jjtGetNumChildren()); |
| ChildNodeIterator it = new ChildNodeIterator(node); |
| while (it.hasNext()) { |
| Node n = it.nextNode(); |
| if (n instanceof ASTdomain) |
| results.add(buildString((ASTdomain)n, true)); |
| else |
| throw new IllegalStateException(); |
| } |
| return new DomainList(results, true); |
| } |
| |
| private Mailbox buildAddrSpec(ASTaddr_spec node) { |
| return buildAddrSpec(null, node); |
| } |
| private Mailbox buildAddrSpec(DomainList route, ASTaddr_spec node) { |
| ChildNodeIterator it = new ChildNodeIterator(node); |
| String localPart = buildString((ASTlocal_part)it.nextNode(), true); |
| String domain = buildString((ASTdomain)it.nextNode(), true); |
| return new Mailbox(route, localPart, domain); |
| } |
| |
| |
| private String buildString(SimpleNode node, boolean stripSpaces) { |
| Token head = node.firstToken; |
| Token tail = node.lastToken; |
| StringBuffer out = new StringBuffer(); |
| |
| while (head != tail) { |
| out.append(head.image); |
| head = head.next; |
| if (!stripSpaces) |
| addSpecials(out, head.specialToken); |
| } |
| out.append(tail.image); |
| |
| return out.toString(); |
| } |
| |
| private void addSpecials(StringBuffer out, Token specialToken) { |
| if (specialToken != null) { |
| addSpecials(out, specialToken.specialToken); |
| out.append(specialToken.image); |
| } |
| } |
| |
| private static class ChildNodeIterator implements Iterator<Node> { |
| |
| private SimpleNode simpleNode; |
| private int index; |
| private int len; |
| |
| public ChildNodeIterator(SimpleNode simpleNode) { |
| this.simpleNode = simpleNode; |
| this.len = simpleNode.jjtGetNumChildren(); |
| this.index = 0; |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean hasNext() { |
| return index < len; |
| } |
| |
| public Node next() { |
| return nextNode(); |
| } |
| |
| public Node nextNode() { |
| return simpleNode.jjtGetChild(index++); |
| } |
| |
| } |
| } |