package jeql.std.function;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import jeql.api.annotation.Metadata;
import jeql.api.function.FunctionClass;
import jeql.api.row.ArrayRowList;
import jeql.api.row.BasicRow;
import jeql.api.row.RowSchema;
import jeql.api.table.Table;
import jeql.io.ExtensionFilenameFilter;
/**
* File functions which either interrogate the file system
* or modify it.
*
* @author Martin Davis
*
*/
public class FileSysFunction
implements FunctionClass
{
public static boolean mkdirs(String path)
{
return (new File(path)).mkdirs();
}
public static boolean mkdir(String path)
{
return (new File(path)).mkdir();
}
public static boolean isFile(String path)
{
return (new File(path)).isFile();
}
public static boolean isDir(String path)
{
return (new File(path)).isDirectory();
}
public static boolean rename(String oldName, String newName)
{
return (new File(oldName)).renameTo(new File(newName));
}
public static boolean delete(String file)
{
return (new File(file)).delete();
}
/**
* Moves a file to a new directory and name,
* creating the directory if necessary.
*
* @param file
* @param newName
* @return
*/
public static boolean move(String oldName, String newName)
{
// create dest directory if it doesnt' exist
String newDir = FileFunction.parent(newName);
(new File(newDir)).mkdirs();
return (new File(oldName)).renameTo(new File(newName));
}
public static boolean copy(String sourceName, String destName)
{
try {
copy(new File(sourceName), new File(destName));
return true;
}
catch (IOException ex) {
ex.printStackTrace();
// can't do much with this so eat it
}
return false;
}
private static void copy(File sourceFile, File destFile)
throws IOException
{
File destDir = destFile.getParentFile();
destDir.mkdirs();
if(! destFile.exists()) {
destFile.createNewFile();
}
FileChannel source = null;
FileChannel destination = null;
try {
source = new FileInputStream(sourceFile).getChannel();
destination = new FileOutputStream(destFile).getChannel();
destination.transferFrom(source, 0, source.size());
}
finally {
if (source != null) {
source.close();
}
if (destination != null) {
destination.close();
}
}
}
private static String COLNAME_FILENAME = "filename";
private static String COLNAME_ISDIR = "isDir";
private static RowSchema getFileListSchema()
{
RowSchema schema = new RowSchema(2);
schema.setColumnDef(0, COLNAME_FILENAME, String.class);
schema.setColumnDef(1, COLNAME_ISDIR, Boolean.class);
return schema;
}
public static Table listFiles(String dirname)
{
return listFilesFiltered(dirname, null);
}
public static Table listFiles(String dirname, String pattern)
{
if (pattern.startsWith("*."))
return listFilesFiltered(dirname, new ExtensionFilenameFilter(FileFunction.ext(pattern)));
throw new IllegalArgumentException("File pattern '" + pattern + "'is not supported");
}
private static Table listFilesFiltered(String dirname, FilenameFilter filter)
{
RowSchema schema = new RowSchema(1);
schema.setColumnDef(0, COLNAME_FILENAME, String.class);
ArrayRowList rs = new ArrayRowList(schema);
String[] files;
if (filter == null)
files = (new File(dirname)).list();
else
files = (new File(dirname)).list(filter);
int nfiles = 0;
if (files != null) nfiles = files.length;
for (int i = 0; i < nfiles; i += 1) {
BasicRow row = new BasicRow(1);
row.setValue(0, files[i]);
rs.add(row);
}
Table t = new Table(rs);
return t;
}
@Metadata (
description = "Lists all files in a directory tree"
)
public static Table listAllFiles(
@Metadata (name = "dirName", description = "directory name or path" )
String dirname)
{
return listAllFilesFiltered(dirname, null, false);
}
@Metadata (description = "Lists all files in a directory tree" )
public static Table listAllDirsAndFiles(
@Metadata (name = "dirName", description = "directory name or path" )
String dirname)
{
return listAllFilesFiltered(dirname, null, true);
}
@Metadata (
description = "Lists all files in a directory tree which match a pattern"
)
public static Table listAllFiles(
@Metadata (name = "dirName", description = "directory name or path" )
String dirname,
@Metadata (name = "pattern", description = "filename pattern" )
String pattern)
{
if (pattern.startsWith("*."))
return listAllFilesFiltered(dirname, new ExtensionFilenameFilter(FileFunction.ext(pattern)), false);
throw new IllegalArgumentException("File pattern '" + pattern + "'is not supported");
}
private static Table listAllFilesFiltered(String dirname, FilenameFilter filter, boolean includeDirs)
{
ArrayRowList rs = new ArrayRowList(getFileListSchema());
listAllFilesFiltered(dirname, filter, includeDirs, rs);
Table t = new Table(rs);
return t;
}
private static void listAllFilesFiltered(String dirname, FilenameFilter filter, boolean includeDirs,
ArrayRowList rowList)
{
File[] files;
if (filter == null)
files = (new File(dirname)).listFiles();
else
files = (new File(dirname)).listFiles(filter);
int nfiles = 0;
if (files != null) nfiles = files.length;
for (int i = 0; i < nfiles; i += 1) {
boolean isFile = files[i].isFile();
if (isFile || includeDirs) {
BasicRow row = new BasicRow(2);
row.setValue(0, files[i].toString());
row.setValue(1, new Boolean(! isFile));
rowList.add(row);
}
if (! isFile) {
listAllFilesFiltered(files[i].toString(), filter, includeDirs, rowList);
}
}
}
}