/**
   * Returns <code>true</code> for regular files (not directories) with an <code>exe</code>
   * extension (case-insensitive comparison).
   *
   * @param file the file to test
   * @return <code>true</code> for regular files (not directories) with an <code>exe</code>
   *     extension (case-insensitive comparison).
   */
  @Override
  public boolean isApplication(AbstractFile file) {
    String extension = file.getExtension();

    // the isDirectory() test comes last as it is I/O bound
    return extension != null && extension.equalsIgnoreCase("exe") && !file.isDirectory();
  }
  /**
   * It is possible to add several files with same name to the Trash. These files are distinguished
   * by _N appended to the name, where _N is rising int number. <br>
   * This method tries to find first empty <code>filename_N.ext</code>.
   *
   * @param file File to be deleted
   * @return Suitable filename in trash (without .trashinfo extension)
   */
  private String getUniqueFilename(AbstractFile file) throws IOException {
    // try if no previous file in trash exists
    if (!TRASH_FILES_SUBFOLDER.getChild(file.getName()).exists()) return file.getName();

    String rawName = file.getNameWithoutExtension();
    String extension = file.getExtension();

    // find first empty filename in format filename_N.ext
    String filename;
    int count = 1;
    while (true) {
      filename = rawName + "_" + count++;
      if (extension != null) {
        filename += "." + extension;
      }

      if (!TRASH_FILES_SUBFOLDER.getChild(filename).exists()) return filename;
    }
  }
 @Override
 public String getExtension() {
   return file.getExtension();
 }
  public int compare(AbstractFile f1, AbstractFile f2) {
    long diff;

    boolean is1Directory = f1.isDirectory();
    boolean is2Directory = f2.isDirectory();

    if (directoriesFirst) {
      if (is1Directory && !is2Directory)
        return -1; // ascending has no effect on the result (a directory is always first) so let's
      // return
      else if (is2Directory && !is1Directory)
        return 1; // ascending has no effect on the result (a directory is always first) so let's
      // return
      // At this point, either both files are directories or none of them are
    }

    if (criterion == SIZE_CRITERION) {
      // Consider that directories have a size of 0
      long fileSize1 = is1Directory ? 0 : f1.getSize();
      long fileSize2 = is2Directory ? 0 : f2.getSize();

      // Returns file1 size - file2 size, file size of -1 (unavailable) is considered as enormous
      // (max long value)
      diff =
          (fileSize1 == -1 ? Long.MAX_VALUE : fileSize1)
              - (fileSize2 == -1 ? Long.MAX_VALUE : fileSize2);
    } else if (criterion == DATE_CRITERION) {
      diff = f1.getDate() - f2.getDate();
    } else if (criterion == PERMISSIONS_CRITERION) {
      diff = f1.getPermissions().getIntValue() - f2.getPermissions().getIntValue();
    } else if (criterion == EXTENSION_CRITERION) {
      diff = compareStrings(f1.getExtension(), f2.getExtension(), true, true);
    } else if (criterion == OWNER_CRITERION) {
      diff = compareStrings(f1.getOwner(), f2.getOwner(), true, true);
    } else if (criterion == GROUP_CRITERION) {
      diff = compareStrings(f1.getGroup(), f2.getGroup(), true, true);
    } else { // criterion == NAME_CRITERION
      diff = compareStrings(f1.getName(), f2.getName(), true);
      if (diff == 0) {
        // This should never happen unless the current filesystem allows a directory to have
        // several files with different case variations of the same name.
        // AFAIK, no OS/filesystem allows this, but just to be safe.

        // Case-sensitive name comparison
        diff = compareStrings(f1.getName(), f2.getName(), false);
      }
    }

    if (criterion != NAME_CRITERION
        && diff == 0) // If both files have the same criterion's value, compare names
    diff = compareStrings(f1.getName(), f2.getName(), true, false);

    // Cast long value to int, without overflowing the int if the long value exceeds the min or max
    // int value
    int intValue;

    if (diff > Integer.MAX_VALUE) intValue = Integer.MAX_VALUE; // 2147483647
    else if (diff
        < Integer.MIN_VALUE
            + 1) // Need that +1 so that the int is not overflowed if ascending order is enabled
      // (i.e. int is negated)
      intValue = Integer.MIN_VALUE + 1; // 2147483647
    else intValue = (int) diff;

    return ascending
        ? intValue
        : -intValue; // Note: ascending is used more often, more efficient to negate for descending
  }