244 lines
7.5 KiB
Java
244 lines
7.5 KiB
Java
/****************************************************************
|
|
* 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++);
|
|
}
|
|
|
|
}
|
|
}
|