/*
* Copyright (c) 2012 Hai Bison
*
* See the file LICENSE at the root directory of this project for copying
* permission.
*/
package group.pals.android.lib.ui.filechooser.utils;
import group.pals.android.lib.ui.filechooser.R;
import group.pals.android.lib.ui.filechooser.io.IFile;
import group.pals.android.lib.ui.filechooser.io.localfile.ParentFile;
import group.pals.android.lib.ui.filechooser.services.IFileProvider;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Utilities for files.
*
* @author Hai Bison
* @since v4.3 beta
*
*/
public class FileUtils {
/**
* Map of the regexes for file types corresponding to resource IDs for
* icons.
*/
private static final Map<String, Integer> _MapFileIcons = new HashMap<String, Integer>();
static {
_MapFileIcons.put(MimeTypes._RegexFileTypeAudios, R.drawable.afc_file_audio);
_MapFileIcons.put(MimeTypes._RegexFileTypeVideos, R.drawable.afc_file_video);
_MapFileIcons.put(MimeTypes._RegexFileTypeImages, R.drawable.afc_file_image);
_MapFileIcons.put(MimeTypes._RegexFileTypeCompressed, R.drawable.afc_file_compressed);
_MapFileIcons.put(MimeTypes._RegexFileTypePlainTexts, R.drawable.afc_file_plain_text);
}
private static boolean accessDenied(IFile f) {
if (f.isFile()) {
return !f.canRead();
}
if (!(f instanceof File)) {
return false;
}
final File file = (File)f;
if (android.os.Build.VERSION.SDK_INT >= 9) {
return !file.canExecute() || !file.canRead();
} else {
return !file.canRead();
}
}
/**
* Gets resource icon ID of an {@link IFile}.
*
* @param file
* {@link IFile}
* @return the resource icon ID
*/
public static int getResIcon(IFile file, final IFileProvider.FilterMode filterMode) {
if (file == null || !file.exists())
return R.drawable.afc_item_file;
if (file.isFile()) {
//String filename = file.getName();
//for (String r : _MapFileIcons.keySet())
// if (filename.matches(r))
// return _MapFileIcons.get(r);
return R.drawable.afc_item_file;
} else if (file.isDirectory()) {
if (filterMode == IFileProvider.FilterMode.DirectoriesOnly) {
if (file instanceof File && !((File)file).canWrite()) {
if (file instanceof ParentFile) {
return R.drawable.afc_item_folder;
} else if (accessDenied(file)) {
return R.drawable.afc_item_folder;
} else {
return R.drawable.afc_folder_locked;
}
} else {
return R.drawable.afc_folder;
}
} else {
return R.drawable.afc_item_folder;
}
}
return R.drawable.afc_item_file;
}// getResIcon()
public static boolean isAccessible(IFile file, final String regexp) {
if (file == null || !file.exists()) {
return false;
}
if (accessDenied(file)) {
return false;
}
if (file.isFile()) {
return regexp == null || file.getName().matches(regexp);
} else if (file.isDirectory()) {
return true;
}
return false;
}// isAccessible()
/**
* Checks whether the filename given is valid or not.<br>
* See <a href="http://en.wikipedia.org/wiki/Filename">wiki</a> for more
* information.
*
* @param name
* name of the file
* @return {@code true} if the {@code name} is valid, and vice versa (if it
* contains invalid characters or it is {@code null}/ empty)
*/
public static boolean isFilenameValid(String name) {
return name != null && name.trim().matches("[^\\\\/?%*:|\"<>]+");
}
/**
* Deletes a file or directory.
*
* @param file
* {@link IFile}
* @param fileProvider
* {@link IFileProvider}
* @param recursive
* if {@code true} and {@code file} is a directory, browses the
* directory and deletes all of its sub files
* @return the thread which is deleting files
*/
public static Thread createDeleteFileThread(final IFile file, final IFileProvider fileProvider,
final boolean recursive) {
return new Thread() {
@Override
public void run() {
deleteFile(file);
}// run()
private void deleteFile(IFile file) {
if (isInterrupted())
return;
if (file.isFile()) {
file.delete();
return;
} else if (!file.isDirectory())
return;
if (!recursive) {
file.delete();
return;
}
try {
List<IFile> files = fileProvider.listAllFiles(file);
if (files == null) {
file.delete();
return;
}
for (IFile f : files) {
if (isInterrupted())
return;
if (f.isFile())
f.delete();
else if (f.isDirectory()) {
if (recursive)
deleteFile(f);
else
f.delete();
}
}
file.delete();
} catch (Throwable t) {
// TODO
}
}// deleteFile()
};
}// createDeleteFileThread()
}