blob: 30b8abee1da7f1450c1b8ea8f4cc059858d9eb0e [file] [log] [blame]
/****************************************************************
* 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 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;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 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 list = new ArrayList();
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 results = new ArrayList();
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 results = new ArrayList(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 {
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 Object next() {
return nextNode();
}
public Node nextNode() {
return simpleNode.jjtGetChild(index++);
}
}
}