1 19 package org.netbeans.api.retouche.source; 20 21 import java.io.IOException ; 22 import java.util.ArrayList ; 23 import java.util.Collection ; 24 import java.util.HashMap ; 25 import java.util.List ; 26 import java.util.Map ; 27 import java.util.Map.Entry; 28 import java.util.logging.Level ; 29 import java.util.logging.Logger ; 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 64 public abstract class SourceTaskFactory { 65 66 private static final Logger LOG = Logger.getLogger(SourceTaskFactory.class.getName()); 67 static final String BEFORE_ADDING_REMOVING_TASKS = "beforeAddingRemovingTasks"; static final String FILEOBJECTS_COMPUTATION = "fileObjectsComputation"; 70 private final Phase phase; 71 private final Priority priority; 72 73 78 protected SourceTaskFactory(Phase phase, Priority priority) { 79 this.phase = phase; 80 this.priority = priority; 81 this.file2Task = new HashMap <FileObject, CancellableTask<CompilationInfo>>(); 82 this.file2JS = new HashMap <FileObject, Source>(); 83 } 84 85 93 protected abstract CancellableTask<CompilationInfo> createTask(FileObject file); 94 95 110 protected abstract Collection <FileObject> getFileObjects(); 111 112 115 protected final void fileObjectsChanged() { 116 LOG.log(Level.FINEST, FILEOBJECTS_COMPUTATION); 117 118 final List <FileObject> currentFiles = new ArrayList (getFileObjects()); 119 120 if (SYNCHRONOUS_EVENTS) { 121 stateChangedImpl(currentFiles); 122 } else { 123 WORKER.post(new Runnable () { 124 public void run() { 125 stateChangedImpl(currentFiles); 126 } 127 }); 128 } 129 } 130 131 133 static boolean SYNCHRONOUS_EVENTS = false; 134 135 private void stateChangedImpl(List <FileObject> currentFiles) { 136 Map <Source, CancellableTask<CompilationInfo>> toRemove = new HashMap <Source, CancellableTask<CompilationInfo>>(); 137 Map <Source, CancellableTask<CompilationInfo>> toAdd = new HashMap <Source, CancellableTask<CompilationInfo>>(); 138 139 synchronized (this) { 140 List <FileObject> addedFiles = new ArrayList (currentFiles); 141 List <FileObject> removedFiles = new ArrayList (file2Task.keySet()); 142 143 addedFiles.removeAll(file2Task.keySet()); 144 removedFiles.removeAll(currentFiles); 145 146 for (FileObject r : removedFiles) { 148 Source source = file2JS.remove(r); 149 150 if (source == null) { 151 continue; 153 } 154 155 toRemove.put(source, file2Task.remove(r)); 156 } 157 158 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"); } catch (IOException ex) { 191 ErrorManager.getDefault().notify(ex); 192 } 193 } 194 } 195 196 201 protected final synchronized void reschedule(FileObject file) throws IllegalArgumentException { 202 Source source = file2JS.get(file); 203 204 if (source == null) { 205 return ; 207 } 208 209 CancellableTask<CompilationInfo> task = file2Task.get(file); 210 211 if (task == null) { 212 return ; 214 } 215 216 ACCESSOR2.rescheduleTask(source, task); 217 } 218 219 private final Map <FileObject, CancellableTask<CompilationInfo>> file2Task; 220 private final Map <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 { 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 ; 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 |