public synchronized Map<FileNaming, Integer> refresh(
      final FileNaming folderName, Runnable[] task) {
    Map<FileNaming, Integer> retVal = new HashMap<FileNaming, Integer>();
    Set<FileNaming> e = new HashSet<FileNaming>(getExisting(false));
    Set<FileNaming> nE = new HashSet<FileNaming>(getNotExisting(false));

    if (isStatus(ChildrenSupport.SOME_CHILDREN_CACHED)) {
      Set<FileNaming> existingToCheck = new HashSet<FileNaming>(e);
      for (FileNaming fnToCheck : existingToCheck) {
        FileNaming fnRescanned = rescanChild(folderName, fnToCheck.getName(), true);
        if (fnRescanned == null) {
          retVal.put(fnToCheck, ChildrenCache.REMOVED_CHILD);
        }
      }

      Set<FileNaming> notExistingToCheck = new HashSet<FileNaming>(nE);
      for (FileNaming fnToCheck : notExistingToCheck) {
        assert fnToCheck != null;
        FileNaming fnRescanned = rescanChild(folderName, fnToCheck.getName(), true);
        if (fnRescanned != null) {
          retVal.put(fnToCheck, ChildrenCache.ADDED_CHILD);
        }
      }
    } else if (isStatus(ChildrenSupport.ALL_CHILDREN_CACHED)) {
      retVal = rescanChildren(folderName, true, task);
    }
    return retVal;
  }
 private synchronized void addChild(final FileNaming folderName, final FileNaming childName) {
   assert childName != null;
   assert childName.getParent().equals(folderName)
       : "childName: " + childName.getFile() + " folderName: " + folderName.getFile();
   getExisting().add(childName);
   getNotExisting().remove(childName);
 }
 private static Set<FileNaming> deepMinus(Set<FileNaming> base, Set<FileNaming> minus) {
   HashMap<FileNaming, FileNaming> detract = new HashMap<FileNaming, FileNaming>(base.size() * 2);
   for (FileNaming fn : base) {
     detract.put(fn, fn);
   }
   assert minus != null;
   for (FileNaming mm : minus) {
     FileNaming orig = detract.remove(mm);
     if (orig != null && orig.isFile() != mm.isFile()) {
       detract.put(orig, orig);
     }
   }
   return detract.keySet();
 }
  private FileNaming rescanChild(
      final FileNaming folderName, final String childName, boolean ignoreCache) {
    final File folder = folderName.getFile();
    final File child = new File(folder, childName);
    final FileInfo fInfo = new FileInfo(child);

    FileNaming retval =
        (fInfo.isConvertibleToFileObject())
            ? NamingFactory.fromFile(folderName, child, ignoreCache)
            : null;
    if (retval != null) {
      addChild(folderName, retval);
    } else {
      FileName fChild =
          new FileName(folderName, child, null) {
            @Override
            public boolean isDirectory() {
              return false;
            }

            @Override
            public boolean isFile() {
              return false;
            }
          };

      removeChild(folderName, fChild);
    }

    return retval;
  }
 public synchronized void removeChild(final FileNaming folderName, final FileNaming childName) {
   assert childName != null;
   getExisting().remove(childName);
   if (childName.getParent().equals(folderName)) {
     getNotExisting().add(childName);
   }
 }
  private FileNaming lookupChildInCache(
      final FileNaming folder, final String childName, boolean lookupExisting) {
    final File f = new File(folder.getFile(), childName);
    final Integer id = NamingFactory.createID(f);

    class FakeNaming implements FileNaming {
      public FileNaming lastEqual;

      public String getName() {
        return childName;
      }

      public FileNaming getParent() {
        return folder;
      }

      public boolean isRoot() {
        return false;
      }

      public File getFile() {
        return f;
      }

      public Integer getId() {
        return id;
      }

      public FileNaming rename(String name, ProvidedExtensions.IOHandler h) {
        // not implemented, as it will not be called
        throw new IllegalStateException();
      }

      @Override
      public boolean equals(Object obj) {
        if (hashCode() == obj.hashCode() && getName().equals(((FileNaming) obj).getName())) {
          assert lastEqual == null : "Just one can be there"; // NOI18N
          if (obj instanceof FileNaming) {
            lastEqual = (FileNaming) obj;
          }
          return true;
        }
        return false;
      }

      @Override
      public int hashCode() {
        return id.intValue();
      }

      public boolean isFile() {
        return this.getFile().isFile();
      }

      public boolean isDirectory() {
        return !isFile();
      }
    }
    FakeNaming fake = new FakeNaming();

    final Set<FileNaming> cache = (lookupExisting) ? getExisting(false) : getNotExisting(false);
    if (cache.contains(fake)) {
      assert fake.lastEqual != null : "If cache contains the object, we set lastEqual"; // NOI18N
      assert fake.lastEqual.getName().equals(childName)
          : "childName: " + childName + " equals: " + fake.lastEqual;
      return fake.lastEqual;
    } else {
      return null;
    }
  }
  private Map<FileNaming, Integer> rescanChildren(
      final FileNaming folderName, final boolean ignoreCache, Runnable[] task) {
    final Map<FileNaming, Integer> retval = new IdentityHashMap<FileNaming, Integer>();

    final File folder = folderName.getFile();
    assert folderName.getFile().getAbsolutePath().equals(folderName.toString());

    class IOJob implements Runnable {
      boolean folderExists;
      Set<FileNaming> newChildren;

      @Override
      public void run() {
        final File[] children = folder.listFiles();
        if (children != null) {
          newChildren = new LinkedHashSet<FileNaming>();
          for (int i = 0; i < children.length; i++) {
            final FileInfo fInfo = new FileInfo(children[i], 1);
            if (fInfo.isConvertibleToFileObject()) {
              FileNaming child = NamingFactory.fromFile(folderName, children[i], ignoreCache);
              newChildren.add(child);
            }
          }
        } else {
          folderExists = folder.exists();
          // #150009 - children == null -> folder does not exists, or an I/O error occurs
          // folder.listFiles() failed with I/O exception - do not remove children
        }
      }
    }
    IOJob job;
    if (task[0] instanceof IOJob) {
      job = (IOJob) task[0];
    } else {
      task[0] = new IOJob();
      return null;
    }

    if (job.newChildren == null) {
      if (job.folderExists) { // #150009 - children == null -> folder does not exists, or an I/O
                              // error occurs
        // folder.listFiles() failed with I/O exception - do not remove children
        return retval;
      }
      job.newChildren = new LinkedHashSet<FileNaming>();
    }

    Set<FileNaming> deleted = deepMinus(getExisting(false), job.newChildren);
    for (FileNaming fnRem : deleted) {
      removeChild(folderName, fnRem);
      retval.put(fnRem, ChildrenCache.REMOVED_CHILD);
    }

    Set<FileNaming> added = deepMinus(job.newChildren, getExisting(false));
    for (FileNaming fnAdd : added) {
      addChild(folderName, fnAdd);
      retval.put(fnAdd, ChildrenCache.ADDED_CHILD);
    }

    return retval;
  }