001    /****************************************************************
002     * Licensed to the Apache Software Foundation (ASF) under one   *
003     * or more contributor license agreements.  See the NOTICE file *
004     * distributed with this work for additional information        *
005     * regarding copyright ownership.  The ASF licenses this file   *
006     * to you under the Apache License, Version 2.0 (the            *
007     * "License"); you may not use this file except in compliance   *
008     * with the License.  You may obtain a copy of the License at   *
009     *                                                              *
010     *   http://www.apache.org/licenses/LICENSE-2.0                 *
011     *                                                              *
012     * Unless required by applicable law or agreed to in writing,   *
013     * software distributed under the License is distributed on an  *
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015     * KIND, either express or implied.  See the License for the    *
016     * specific language governing permissions and limitations      *
017     * under the License.                                           *
018     ****************************************************************/
019    
020    package org.apache.james.mime4j.field.address;
021    
022    import org.apache.james.mime4j.field.address.parser.AddressListParser;
023    import org.apache.james.mime4j.field.address.parser.ParseException;
024    
025    import java.io.Serializable;
026    import java.io.StringReader;
027    import java.util.AbstractList;
028    import java.util.ArrayList;
029    import java.util.Collections;
030    import java.util.List;
031    
032    /**
033     * An immutable, random-access list of Address objects.
034     */
035    public class AddressList extends AbstractList<Address> implements Serializable {
036    
037        private static final long serialVersionUID = 1L;
038    
039        private final List<? extends Address> addresses;
040    
041        /**
042         * @param addresses
043         *            A List that contains only Address objects.
044         * @param dontCopy
045         *            true iff it is not possible for the addresses list to be
046         *            modified by someone else.
047         */
048        public AddressList(List<? extends Address> addresses, boolean dontCopy) {
049            if (addresses != null)
050                this.addresses = dontCopy ? addresses : new ArrayList<Address>(
051                        addresses);
052            else
053                this.addresses = Collections.emptyList();
054        }
055    
056        /**
057         * The number of elements in this list.
058         */
059        @Override
060        public int size() {
061            return addresses.size();
062        }
063    
064        /**
065         * Gets an address.
066         */
067        @Override
068        public Address get(int index) {
069            return addresses.get(index);
070        }
071    
072        /**
073         * Returns a flat list of all mailboxes represented in this address list.
074         * Use this if you don't care about grouping.
075         */
076        public MailboxList flatten() {
077            // in the common case, all addresses are mailboxes
078            boolean groupDetected = false;
079            for (Address addr : addresses) {
080                if (!(addr instanceof Mailbox)) {
081                    groupDetected = true;
082                    break;
083                }
084            }
085    
086            if (!groupDetected) {
087                @SuppressWarnings("unchecked")
088                final List<Mailbox> mailboxes = (List<Mailbox>) addresses;
089                return new MailboxList(mailboxes, true);
090            }
091    
092            List<Mailbox> results = new ArrayList<Mailbox>();
093            for (Address addr : addresses) {
094                addr.addMailboxesTo(results);
095            }
096    
097            // copy-on-construct this time, because subclasses
098            // could have held onto a reference to the results
099            return new MailboxList(results, false);
100        }
101    
102        /**
103         * Dumps a representation of this address list to stdout, for debugging
104         * purposes.
105         */
106        public void print() {
107            for (Address addr : addresses) {
108                System.out.println(addr.toString());
109            }
110        }
111    
112        /**
113         * Parse the address list string, such as the value of a From, To, Cc, Bcc,
114         * Sender, or Reply-To header.
115         * 
116         * The string MUST be unfolded already.
117         */
118        public static AddressList parse(String rawAddressList)
119                throws ParseException {
120            AddressListParser parser = new AddressListParser(new StringReader(
121                    rawAddressList));
122            return Builder.getInstance().buildAddressList(parser.parseAddressList());
123        }
124    
125        /**
126         * Test console.
127         */
128        public static void main(String[] args) throws Exception {
129            java.io.BufferedReader reader = new java.io.BufferedReader(
130                    new java.io.InputStreamReader(System.in));
131            while (true) {
132                try {
133                    System.out.print("> ");
134                    String line = reader.readLine();
135                    if (line.length() == 0 || line.toLowerCase().equals("exit")
136                            || line.toLowerCase().equals("quit")) {
137                        System.out.println("Goodbye.");
138                        return;
139                    }
140                    AddressList list = parse(line);
141                    list.print();
142                } catch (Exception e) {
143                    e.printStackTrace();
144                    Thread.sleep(300);
145                }
146            }
147        }
148    }