/**
   * Re-run task created by this factory for given file. If the task has not yet been run, does
   * nothing.
   *
   * @param file task created by this factory for this file is re-run.
   */
  protected final synchronized void reschedule(FileObject file) throws IllegalArgumentException {
    VisageSource source = file2JS.get(file);

    if (source == null) {
      //            throw new IllegalArgumentException("No VisageSource for given file.");
      return;
    }

    CancellableTask<CompilationInfo> task = file2Task.get(file);

    if (task == null) {
      //                    throw new IllegalArgumentException("This factory did not created any
      // task for " + FileUtil.getFileDisplayName(file)); // NOI18N
      return;
    }

    VisageTaskProcessor.rescheduleTask(source, task);
  }
  private void stateChangedImpl(List<FileObject> currentFiles) {
    Map<VisageSource, CancellableTask<CompilationInfo>> toRemove =
        new HashMap<VisageSource, CancellableTask<CompilationInfo>>();
    Map<VisageSource, CancellableTask<CompilationInfo>> toAdd =
        new HashMap<VisageSource, CancellableTask<CompilationInfo>>();

    synchronized (this) {
      List<FileObject> addedFiles = new ArrayList<FileObject>(currentFiles);
      List<FileObject> removedFiles = new ArrayList<FileObject>(file2Task.keySet());

      addedFiles.removeAll(file2Task.keySet());
      removedFiles.removeAll(currentFiles);

      // remove old tasks:
      for (FileObject r : removedFiles) {
        VisageSource source = file2JS.remove(r);

        if (source == null) {
          // TODO: log
          continue;
        }

        toRemove.put(source, file2Task.remove(r));
      }

      // add new tasks:
      for (FileObject a : addedFiles) {
        if (a == null) continue;
        if (!a.isValid()) {
          continue;
        }
        VisageSource js = VisageSource.forFileObject(a);

        if (js != null) {
          CancellableTask<CompilationInfo> task = createTask(a);

          toAdd.put(js, task);

          file2Task.put(a, task);
          file2JS.put(a, js);
        }
      }
    }

    LOG.log(Level.FINEST, BEFORE_ADDING_REMOVING_TASKS);

    for (Entry<VisageSource, CancellableTask<CompilationInfo>> e : toRemove.entrySet()) {
      VisageTaskProcessor.removePhaseCompletionTask(e.getKey(), e.getValue());
    }

    for (Entry<VisageSource, CancellableTask<CompilationInfo>> e : toAdd.entrySet()) {
      try {
        VisageTaskProcessor.addPhaseCompletionTask(e.getKey(), e.getValue(), phase, priority);
        //            } catch (FileObjects.InvalidFileException ie) {
        //                LOG.info("VisageSource.addPhaseCompletionTask called on deleted file");
        //    //NOI18N
      } catch (IOException ex) {
        ErrorManager.getDefault().notify(ex);
      }
    }
  }