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 org.apache.james.mime4j.field.address.parser.AddressListParser;
23d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport org.apache.james.mime4j.field.address.parser.ParseException;
24d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
25d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport java.io.StringReader;
26d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenimport java.util.ArrayList;
27d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
28d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen/**
29d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen * An immutable, random-access list of Address objects.
30d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen *
31d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen *
32d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen */
33d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chenpublic class AddressList {
34d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
35d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	private ArrayList<Address> addresses;
36d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
37d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	/**
38d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * @param addresses An ArrayList that contains only Address objects.
39d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * @param dontCopy true iff it is not possible for the addresses ArrayList to be modified by someone else.
40d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 */
41d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	public AddressList(ArrayList<Address> addresses, boolean dontCopy) {
42d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		if (addresses != null)
43d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			this.addresses = (dontCopy ? addresses : new ArrayList<Address>(addresses));
44d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		else
45d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			this.addresses = new ArrayList<Address>(0);
46d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	}
47d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
48d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	/**
49d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * The number of elements in this list.
50d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 */
51d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	public int size() {
52d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		return addresses.size();
53d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	}
54d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
55d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	/**
56d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * Gets an address.
57d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 */
58d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	public Address get(int index) {
59d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		if (0 > index || size() <= index)
60d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			throw new IndexOutOfBoundsException();
61d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		return addresses.get(index);
62d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	}
63d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
64d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	/**
65d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * Returns a flat list of all mailboxes represented
66d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * in this address list. Use this if you don't care
67d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * about grouping.
68d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 */
69d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	public MailboxList flatten() {
70d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		// in the common case, all addresses are mailboxes
71d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		boolean groupDetected = false;
72d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		for (int i = 0; i < size(); i++) {
73d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			if (!(get(i) instanceof Mailbox)) {
74d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen				groupDetected = true;
75d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen				break;
76d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			}
77d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		}
78d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
79d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		if (!groupDetected)
80d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			return new MailboxList(addresses, true);
81d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
82d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		ArrayList<Address> results = new ArrayList<Address>();
83d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		for (int i = 0; i < size(); i++) {
84d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			Address addr = get(i);
85d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			addr.addMailboxesTo(results);
86d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		}
87d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
88d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		// copy-on-construct this time, because subclasses
89d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		// could have held onto a reference to the results
90d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		return new MailboxList(results, false);
91d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	}
92d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
93d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	/**
94d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * Dumps a representation of this address list to
95d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * stdout, for debugging purposes.
96d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 */
97d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	public void print() {
98d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		for (int i = 0; i < size(); i++) {
99d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			Address addr = get(i);
100d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			System.out.println(addr.toString());
101d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		}
102d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	}
103d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
104d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	/**
105d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * Parse the address list string, such as the value
106d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * of a From, To, Cc, Bcc, Sender, or Reply-To
107d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * header.
108d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 *
109d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * The string MUST be unfolded already.
110d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 */
111d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	public static AddressList parse(String rawAddressList) throws ParseException {
112d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		AddressListParser parser = new AddressListParser(new StringReader(rawAddressList));
113d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		return Builder.getInstance().buildAddressList(parser.parse());
114d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	}
115d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen
116d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	/**
117d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 * Test console.
118d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	 */
119d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	public static void main(String[] args) throws Exception {
120d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
121d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		while (true) {
122d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			try {
123d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen				System.out.print("> ");
124d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen				String line = reader.readLine();
125d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen				if (line.length() == 0 || line.toLowerCase().equals("exit") || line.toLowerCase().equals("quit")) {
126d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen					System.out.println("Goodbye.");
127d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen					return;
128d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen				}
129d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen				AddressList list = parse(line);
130d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen				list.print();
131d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			}
132d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			catch(Exception e) {
133d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen				e.printStackTrace();
134d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen				Thread.sleep(300);
135d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen			}
136d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen		}
137d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen	}
138d186a38568ddec7efcba054ccc2fe8ed9b8945fcNancy Chen}
139