KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > retouche > source > SourceTaskFactory


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.api.retouche.source;
20
21 import java.io.IOException JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.Map.Entry;
28 import java.util.logging.Level JavaDoc;
29 import java.util.logging.Logger JavaDoc;
30 import org.netbeans.api.gsf.CancellableTask;
31 import org.netbeans.api.retouche.source.Source.Priority;
32 import org.openide.filesystems.FileObject;
33 import org.netbeans.api.retouche.source.support.EditorAwareSourceTaskFactory;
34 import org.netbeans.api.retouche.source.support.CaretAwareSourceTaskFactory;
35 import org.netbeans.api.retouche.source.support.LookupBasedSourceTaskFactory;
36 import org.netbeans.modules.retouche.source.parsing.FileObjects;
37 import org.openide.ErrorManager;
38 import org.openide.util.RequestProcessor;
39
40 /**
41  * This class is based on JavaSourceTaskFactory in Retouche
42  * This file is originally from Retouche, the Java Support
43  * infrastructure in NetBeans. I have modified the file as little
44  * as possible to make merging Retouche fixes back as simple as
45  * possible.
46  *
47  *
48  * XXX: SPI?
49  *
50  * A factory for tasks that will be run in the {@link Source} Java parsing harness.
51  *
52  * Please note that there is usually no need to implement this class directly,
53  * as there are support classes for common {@link SourceTaskFactory} implementations.
54  *
55  * This factory should be registered in the global lookup by listing its fully qualified
56  * name in file <code>META-INF/services/org.netbeans.api.java.source.SourceTaskFactory</code>.
57  *
58  * @see EditorAwareSourceTaskFactory
59  * @see CaretAwareSourceTaskFactory
60  * @see LookupBasedSourceTaskFactory
61  *
62  * @author Jan Lahoda
63  */

64 public abstract class SourceTaskFactory {
65
66     private static final Logger JavaDoc LOG = Logger.getLogger(SourceTaskFactory.class.getName());
67             static final String JavaDoc BEFORE_ADDING_REMOVING_TASKS = "beforeAddingRemovingTasks"; //NOI18N
68
static final String JavaDoc FILEOBJECTS_COMPUTATION = "fileObjectsComputation"; //NOI18N
69

70     private final Phase phase;
71     private final Priority priority;
72
73     /**Construct the SourceTaskFactory with given {@link Phase} and {@link Priority}.
74      *
75      * @param phase phase to use for tasks created by {@link #createTask}
76      * @param priority priority to use for tasks created by {@link #createTask}
77      */

78     protected SourceTaskFactory(Phase phase, Priority priority) {
79         this.phase = phase;
80         this.priority = priority;
81         this.file2Task = new HashMap JavaDoc<FileObject, CancellableTask<CompilationInfo>>();
82         this.file2JS = new HashMap JavaDoc<FileObject, Source>();
83     }
84
85     /**Create task for a given file. This task will be registered into the {@link Source}
86      * parsing harness with a given {@link #getPriority priority} and {@link #getPhase phase}.
87      *
88      * Please note that this method should run as quickly as possible.
89      *
90      * @param file for which file the task should be created.
91      * @return created {@link CancellableTask} for a given file.
92      */

93     protected abstract CancellableTask<CompilationInfo> createTask(FileObject file);
94
95     /**Specifies on which files should be registered tasks created by this factory.
96      * On {@link Source}'s corresponding to {@link FileObject}s returned from
97      * this method will be registered tasks created by the {@link #createTask} method
98      * of this factory.
99      *
100      * If this list changes, a change event should be fired to all registered
101      * {@link ChangeListener}s.
102      *
103      * @return list of {@link FileObject} on which tasks from this factory should be
104      * registered.
105      * @see #createTask
106      * @see #addChangeListener
107      * @see EditorAwareSourceTaskFactory
108      * @see CaretAwareSourceTaskFactory
109      */

110     protected abstract Collection JavaDoc<FileObject> getFileObjects();
111
112     /**Notify the infrastructure that the collection of fileobjects has been changed.
113      * The infrastructure calls {@link #getFileObjects()} to get a new collection files.
114      */

115     protected final void fileObjectsChanged() {
116         LOG.log(Level.FINEST, FILEOBJECTS_COMPUTATION);
117
118         final List JavaDoc<FileObject> currentFiles = new ArrayList JavaDoc(getFileObjects());
119
120         if (SYNCHRONOUS_EVENTS) {
121             stateChangedImpl(currentFiles);
122         } else {
123             WORKER.post(new Runnable JavaDoc() {
124                 public void run() {
125                     stateChangedImpl(currentFiles);
126                 }
127             });
128         }
129     }
130
131     /**for tests:
132      */

133     static boolean SYNCHRONOUS_EVENTS = false;
134
135     private void stateChangedImpl(List JavaDoc<FileObject> currentFiles) {
136         Map JavaDoc<Source, CancellableTask<CompilationInfo>> toRemove = new HashMap JavaDoc<Source, CancellableTask<CompilationInfo>>();
137         Map JavaDoc<Source, CancellableTask<CompilationInfo>> toAdd = new HashMap JavaDoc<Source, CancellableTask<CompilationInfo>>();
138         
139         synchronized (this) {
140             List JavaDoc<FileObject> addedFiles = new ArrayList JavaDoc(currentFiles);
141             List JavaDoc<FileObject> removedFiles = new ArrayList JavaDoc(file2Task.keySet());
142             
143             addedFiles.removeAll(file2Task.keySet());
144             removedFiles.removeAll(currentFiles);
145             
146             //remove old tasks:
147
for (FileObject r : removedFiles) {
148                 Source source = file2JS.remove(r);
149                 
150                 if (source == null) {
151                     //TODO: log
152
continue;
153                 }
154                 
155                 toRemove.put(source, file2Task.remove(r));
156             }
157             
158             //add new tasks:
159
for (FileObject a : addedFiles) {
160                 if (a == null)
161                     continue;
162                 if (!a.isValid()) {
163                     continue;
164                 }
165
166                 Source js = Source.forFileObject(a);
167                 
168                 if (js != null) {
169                     CancellableTask<CompilationInfo> task = createTask(a);
170                     
171                     toAdd.put(js, task);
172                     
173                     file2Task.put(a, task);
174                     file2JS.put(a, js);
175                 }
176             }
177         }
178         
179         LOG.log(Level.FINEST, BEFORE_ADDING_REMOVING_TASKS);
180         
181         for (Entry<Source, CancellableTask<CompilationInfo>> e : toRemove.entrySet()) {
182             ACCESSOR2.removePhaseCompletionTask(e.getKey(), e.getValue());
183         }
184         
185         for (Entry<Source, CancellableTask<CompilationInfo>> e : toAdd.entrySet()) {
186             try {
187                 ACCESSOR2.addPhaseCompletionTask(e.getKey(), e.getValue(), phase, priority);
188             } catch (FileObjects.InvalidFileException ie) {
189                 LOG.info("Source.addPhaseCompletionTask called on deleted file"); //NOI18N
190
} catch (IOException JavaDoc ex) {
191                 ErrorManager.getDefault().notify(ex);
192             }
193         }
194     }
195        
196     /**Re-run task created by this factory for given file.
197      * If the task has not yet been run, does nothing.
198      *
199      * @param file task created by this factory for this file is re-run.
200      */

201     protected final synchronized void reschedule(FileObject file) throws IllegalArgumentException JavaDoc {
202         Source source = file2JS.get(file);
203
204         if (source == null) {
205 // throw new IllegalArgumentException("No Source for given file.");
206
return ;
207 }
208         
209         CancellableTask<CompilationInfo> task = file2Task.get(file);
210         
211         if (task == null) {
212 // throw new IllegalArgumentException("This factory did not created any task for " + FileUtil.getFileDisplayName(file)); // NOI18N
213
return ;
214         }
215         
216         ACCESSOR2.rescheduleTask(source, task);
217     }
218
219     private final Map JavaDoc<FileObject, CancellableTask<CompilationInfo>> file2Task;
220     private final Map JavaDoc<FileObject, Source> file2JS;
221
222     private static RequestProcessor WORKER = new RequestProcessor("SourceTaskFactory", 1);
223     
224     static {
225         SourceTaskFactoryManager.ACCESSOR = new SourceTaskFactoryManager.Accessor() {
226             public void fireChangeEvent(SourceTaskFactory f) {
227                 f.fileObjectsChanged();
228             }
229         };
230         ACCESSOR2 = new Accessor2() {
231             public void addPhaseCompletionTask(Source js, CancellableTask<CompilationInfo> task, Phase phase, Priority priority) throws IOException JavaDoc {
232                 js.addPhaseCompletionTask(task, phase, priority);
233             }
234
235             public void removePhaseCompletionTask(Source js, CancellableTask<CompilationInfo> task) {
236                 js.removePhaseCompletionTask(task);
237             }
238
239             public void rescheduleTask(Source js, CancellableTask<CompilationInfo> task) {
240                 js.rescheduleTask(task);
241             }
242         };
243     }
244
245     static interface Accessor2 {
246         public abstract void addPhaseCompletionTask(Source js, CancellableTask<CompilationInfo> task, Phase phase, Priority priority ) throws IOException JavaDoc;
247         public abstract void removePhaseCompletionTask(Source js, CancellableTask<CompilationInfo> task );
248         public abstract void rescheduleTask(Source js, CancellableTask<CompilationInfo> task);
249     }
250     
251     
252     static Accessor2 ACCESSOR2;
253     
254 }
255
Popular Tags