001    /*
002     * Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.javac.comp;
027    
028    import java.util.AbstractQueue;
029    import com.sun.tools.javac.util.Context;
030    import java.util.HashMap;
031    import java.util.Iterator;
032    import java.util.LinkedList;
033    import java.util.Map;
034    import java.util.Queue;
035    import javax.tools.JavaFileObject;
036    
037    /** A queue of all as yet unattributed classes.
038     *
039     *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
040     *  you write code that depends on this, you do so at your own risk.
041     *  This code and its internal interfaces are subject to change or
042     *  deletion without notice.</b>
043     */
044    public class Todo extends AbstractQueue<Env<AttrContext>> {
045        /** The context key for the todo list. */
046        protected static final Context.Key<Todo> todoKey =
047            new Context.Key<Todo>();
048    
049        /** Get the Todo instance for this context. */
050        public static Todo instance(Context context) {
051            Todo instance = context.get(todoKey);
052            if (instance == null)
053                instance = new Todo(context);
054            return instance;
055        }
056    
057        /** Create a new todo list. */
058        protected Todo(Context context) {
059            context.put(todoKey, this);
060        }
061    
062        public void append(Env<AttrContext> env) {
063            add(env);
064        }
065    
066        @Override
067        public Iterator<Env<AttrContext>> iterator() {
068            return contents.iterator();
069        }
070    
071        @Override
072        public int size() {
073            return contents.size();
074        }
075    
076        public boolean offer(Env<AttrContext> e) {
077            if (contents.add(e)) {
078                if (contentsByFile != null)
079                    addByFile(e);
080                return true;
081            } else {
082                return false;
083            }
084        }
085    
086        public Env<AttrContext> poll() {
087            if (size() == 0)
088                return null;
089            Env<AttrContext> env = contents.remove(0);
090            if (contentsByFile != null)
091                removeByFile(env);
092            return env;
093        }
094    
095        public Env<AttrContext> peek() {
096            return (size() == 0 ? null : contents.get(0));
097        }
098    
099        public Queue<Queue<Env<AttrContext>>> groupByFile() {
100            if (contentsByFile == null) {
101                contentsByFile = new LinkedList<Queue<Env<AttrContext>>>();
102                for (Env<AttrContext> env: contents) {
103                    addByFile(env);
104                }
105            }
106            return contentsByFile;
107        }
108    
109        private void addByFile(Env<AttrContext> env) {
110            JavaFileObject file = env.toplevel.sourcefile;
111            if (fileMap == null)
112                fileMap = new HashMap<JavaFileObject, FileQueue>();
113            FileQueue fq = fileMap.get(file);
114            if (fq == null) {
115                fq = new FileQueue();
116                fileMap.put(file, fq);
117                contentsByFile.add(fq);
118            }
119            fq.fileContents.add(env);
120        }
121    
122        private void removeByFile(Env<AttrContext> env) {
123            JavaFileObject file = env.toplevel.sourcefile;
124            FileQueue fq = fileMap.get(file);
125            if (fq == null)
126                return;
127            if (fq.fileContents.remove(env)) {
128                if (fq.isEmpty()) {
129                    fileMap.remove(file);
130                    contentsByFile.remove(fq);
131                }
132            }
133        }
134    
135        LinkedList<Env<AttrContext>> contents = new LinkedList<Env<AttrContext>>();
136        LinkedList<Queue<Env<AttrContext>>> contentsByFile;
137        Map<JavaFileObject, FileQueue> fileMap;
138    
139        class FileQueue extends AbstractQueue<Env<AttrContext>> {
140            @Override
141            public Iterator<Env<AttrContext>> iterator() {
142                return fileContents.iterator();
143            }
144    
145            @Override
146            public int size() {
147                return fileContents.size();
148            }
149    
150            public boolean offer(Env<AttrContext> e) {
151                if (fileContents.offer(e)) {
152                    contents.add(e);
153                    return true;
154                }
155                return false;
156            }
157    
158            public Env<AttrContext> poll() {
159                if (fileContents.size() == 0)
160                    return null;
161                Env<AttrContext> env = fileContents.remove(0);
162                contents.remove(env);
163                return env;
164            }
165    
166            public Env<AttrContext> peek() {
167                return (fileContents.size() == 0 ? null : fileContents.get(0));
168            }
169    
170            LinkedList<Env<AttrContext>> fileContents = new LinkedList<Env<AttrContext>>();
171        }
172    }