1d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen/**************************************************************** 2d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Licensed to the Apache Software Foundation (ASF) under one * 3d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * or more contributor license agreements. See the NOTICE file * 4d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * distributed with this work for additional information * 5d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * regarding copyright ownership. The ASF licenses this file * 6d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * to you under the Apache License, Version 2.0 (the * 7d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * "License"); you may not use this file except in compliance * 8d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * with the License. You may obtain a copy of the License at * 9d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * * 10d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * http://www.apache.org/licenses/LICENSE-2.0 * 11d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * * 12d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Unless required by applicable law or agreed to in writing, * 13d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * software distributed under the License is distributed on an * 14d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 15d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * KIND, either express or implied. See the License for the * 16d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * specific language governing permissions and limitations * 17d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * under the License. * 18d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ****************************************************************/ 19d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 20d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenpackage org.apache.james.mime4j.field.address; 21d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 22d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport java.util.ArrayList; 23d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport java.util.Iterator; 24d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 25d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.decoder.DecoderUtil; 26d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTaddr_spec; 27d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTaddress; 28d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTaddress_list; 29d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTangle_addr; 30d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTdomain; 31d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTgroup_body; 32d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTlocal_part; 33d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTmailbox; 34d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTname_addr; 35d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTphrase; 36d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ASTroute; 37d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.Node; 38d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.SimpleNode; 39d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.Token; 40d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 41d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen/** 42d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * Transforms the JJTree-generated abstract syntax tree 43d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * into a graph of org.apache.james.mime4j.field.address objects. 44d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * 45d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * 46d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */ 47d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenclass Builder { 48d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 49d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private static Builder singleton = new Builder(); 50d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 51d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public static Builder getInstance() { 52d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return singleton; 53d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 54d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 55d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 56d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 57d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public AddressList buildAddressList(ASTaddress_list node) { 58d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ArrayList<Address> list = new ArrayList<Address>(); 59d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen for (int i = 0; i < node.jjtGetNumChildren(); i++) { 60d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ASTaddress childNode = (ASTaddress) node.jjtGetChild(i); 61d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Address address = buildAddress(childNode); 62d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen list.add(address); 63d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 64d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return new AddressList(list, true); 65d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 66d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 67d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private Address buildAddress(ASTaddress node) { 68d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ChildNodeIterator it = new ChildNodeIterator(node); 69d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Node n = it.nextNode(); 70d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (n instanceof ASTaddr_spec) { 71d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return buildAddrSpec((ASTaddr_spec)n); 72d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 73d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else if (n instanceof ASTangle_addr) { 74d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return buildAngleAddr((ASTangle_addr)n); 75d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 76d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else if (n instanceof ASTphrase) { 77d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String name = buildString((ASTphrase)n, false); 78d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Node n2 = it.nextNode(); 79d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (n2 instanceof ASTgroup_body) { 80d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return new Group(name, buildGroupBody((ASTgroup_body)n2)); 81d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 82d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else if (n2 instanceof ASTangle_addr) { 83d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen name = DecoderUtil.decodeEncodedWords(name); 84d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return new NamedMailbox(name, buildAngleAddr((ASTangle_addr)n2)); 85d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 86d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else { 87d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen throw new IllegalStateException(); 88d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 89d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 90d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else { 91d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen throw new IllegalStateException(); 92d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 93d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 94d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 95d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 96d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 97d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private MailboxList buildGroupBody(ASTgroup_body node) { 98d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ArrayList<Address> results = new ArrayList<Address>(); 99d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ChildNodeIterator it = new ChildNodeIterator(node); 100d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen while (it.hasNext()) { 101d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Node n = it.nextNode(); 102d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (n instanceof ASTmailbox) 103d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen results.add(buildMailbox((ASTmailbox)n)); 104d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else 105d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen throw new IllegalStateException(); 106d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 107d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return new MailboxList(results, true); 108d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 109d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 110d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private Mailbox buildMailbox(ASTmailbox node) { 111d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ChildNodeIterator it = new ChildNodeIterator(node); 112d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Node n = it.nextNode(); 113d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (n instanceof ASTaddr_spec) { 114d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return buildAddrSpec((ASTaddr_spec)n); 115d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 116d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else if (n instanceof ASTangle_addr) { 117d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return buildAngleAddr((ASTangle_addr)n); 118d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 119d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else if (n instanceof ASTname_addr) { 120d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return buildNameAddr((ASTname_addr)n); 121d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 122d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else { 123d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen throw new IllegalStateException(); 124d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 125d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 126d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 127d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private NamedMailbox buildNameAddr(ASTname_addr node) { 128d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ChildNodeIterator it = new ChildNodeIterator(node); 129d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Node n = it.nextNode(); 130d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String name; 131d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (n instanceof ASTphrase) { 132d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen name = buildString((ASTphrase)n, false); 133d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 134d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else { 135d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen throw new IllegalStateException(); 136d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 137d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 138d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen n = it.nextNode(); 139d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (n instanceof ASTangle_addr) { 140d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen name = DecoderUtil.decodeEncodedWords(name); 141d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return new NamedMailbox(name, buildAngleAddr((ASTangle_addr) n)); 142d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 143d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else { 144d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen throw new IllegalStateException(); 145d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 146d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 147d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 148d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private Mailbox buildAngleAddr(ASTangle_addr node) { 149d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ChildNodeIterator it = new ChildNodeIterator(node); 150d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen DomainList route = null; 151d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Node n = it.nextNode(); 152d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (n instanceof ASTroute) { 153d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen route = buildRoute((ASTroute)n); 154d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen n = it.nextNode(); 155d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 156d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else if (n instanceof ASTaddr_spec) 157d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ; // do nothing 158d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else 159d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen throw new IllegalStateException(); 160d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 161d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (n instanceof ASTaddr_spec) 162d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return buildAddrSpec(route, (ASTaddr_spec)n); 163d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else 164d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen throw new IllegalStateException(); 165d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 166d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 167d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private DomainList buildRoute(ASTroute node) { 168d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ArrayList<String> results = new ArrayList<String>(node.jjtGetNumChildren()); 169d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ChildNodeIterator it = new ChildNodeIterator(node); 170d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen while (it.hasNext()) { 171d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Node n = it.nextNode(); 172d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (n instanceof ASTdomain) 173d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen results.add(buildString((ASTdomain)n, true)); 174d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen else 175d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen throw new IllegalStateException(); 176d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 177d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return new DomainList(results, true); 178d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 179d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 180d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private Mailbox buildAddrSpec(ASTaddr_spec node) { 181d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return buildAddrSpec(null, node); 182d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 183d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private Mailbox buildAddrSpec(DomainList route, ASTaddr_spec node) { 184d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen ChildNodeIterator it = new ChildNodeIterator(node); 185d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String localPart = buildString((ASTlocal_part)it.nextNode(), true); 186d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen String domain = buildString((ASTdomain)it.nextNode(), true); 187d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return new Mailbox(route, localPart, domain); 188d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 189d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 190d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 191d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private String buildString(SimpleNode node, boolean stripSpaces) { 192d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Token head = node.firstToken; 193d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen Token tail = node.lastToken; 194d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen StringBuffer out = new StringBuffer(); 195d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 196d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen while (head != tail) { 197d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen out.append(head.image); 198d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen head = head.next; 199d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (!stripSpaces) 200d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen addSpecials(out, head.specialToken); 201d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 202d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen out.append(tail.image); 203d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 204d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return out.toString(); 205d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 206d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 207d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private void addSpecials(StringBuffer out, Token specialToken) { 208d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen if (specialToken != null) { 209d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen addSpecials(out, specialToken.specialToken); 210d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen out.append(specialToken.image); 211d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 212d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 213d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 214d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private static class ChildNodeIterator implements Iterator<Node> { 215d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 216d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private SimpleNode simpleNode; 217d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private int index; 218d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen private int len; 219d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 220d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public ChildNodeIterator(SimpleNode simpleNode) { 221d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen this.simpleNode = simpleNode; 222d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen this.len = simpleNode.jjtGetNumChildren(); 223d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen this.index = 0; 224d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 225d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 226d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public void remove() { 227d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen throw new UnsupportedOperationException(); 228d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 229d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 230d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public boolean hasNext() { 231d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return index < len; 232d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 233d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 234d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public Node next() { 235d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return nextNode(); 236d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 237d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 238d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen public Node nextNode() { 239d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen return simpleNode.jjtGetChild(index++); 240d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 241d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen 242d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen } 243d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen} 244