Updated the FileSystem APIs as per review comments.

This commit is contained in:
atanasovg
2014-04-28 15:56:29 +03:00
parent ca4c04badc
commit aa77546c80
5 changed files with 235 additions and 116 deletions

View File

@ -3,22 +3,27 @@
* Gets the Date object specifying the last time this entity was modified.
*/
public lastModified: Date;
/**
* Gets the name of the entity.
*/
public name: string;
/**
* Gets the fully-qualified path (including the extension for a File) of the entity.
*/
public path: string;
/**
* Gets the Folder object representing the parent of this entity. Will be null for a root folder like Documents or Temporary.
*/
public getParent(onError?: (error: any) => any): Folder;
/**
* Deletes the current Entity from the file system.
* Removes (deletes) the current Entity from the file system.
*/
public delete(onSuccess?: () => any, onError?: (error: any) => any);
public remove(onSuccess?: () => any, onError?: (error: any) => any);
/**
* Renames the current entity using the specified name.
*/
@ -26,26 +31,31 @@
}
export declare class File extends FileSystemEntity {
/**
* Checks whether a File with the specified path already exists.
*/
public static exists(path: string): boolean;
/**
* Gets the extension of the file.
*/
public extension: string;
/**
* Gets a value indicating whether the file is currently locked, meaning a background operation associated with this file is running.
*/
public isLocked: boolean;
/**
* Gets or creates a File entity at the specified path.
*/
public static fromPath(path: string, onError?: (error: any) => any): File;
/**
* Checks whether a File with the specified path already exists.
*/
public static exists(path: string): boolean;
/**
* Creates a FileReader object over this file and locks the file until the reader is released.
*/
public openRead(): FileReader;
/**
* Creates a FileWriter object over this file and locks the file until the writer is released.
*/
@ -69,19 +79,15 @@ export declare class Folder extends FileSystemEntity {
public static exists(path: string): boolean;
/**
* Checks whether this Folder contains a file with the specified name.
Checks whether this Folder contains an Entity with the specified name.
The path of the folder is added to the name to resolve the complete path to check for.
*/
public containsFile(name: string): boolean;
/**
* Checks whether this Folder contains a Folder with the specified name.
*/
public containsFolder(name: string): boolean;
public contains(name: string): boolean;
/**
* Deletes all the files and folders (recursively), contained within this Folder.
*/
public empty(onSuccess?: () => any, onError?: (error: any) => any);
public clear(onSuccess?: () => any, onError?: (error: any) => any);
/**
* Gets or creates a File entity with the specified name within this Folder.
@ -89,15 +95,22 @@ export declare class Folder extends FileSystemEntity {
public getFile(name: string, onError?: (error: any) => any): File;
/**
* Gets or creates a Folder entity with the specified name within this Folder.
*/
* Gets or creates a Folder entity with the specified name within this Folder.
*/
public getFolder(name: string, onError?: (error: any) => any): Folder;
/**
* Gets all the top-level FileSystem entities residing within this Folder.
* Gets all the top-level entities residing within this folder.
*/
public enumEntities(onSuccess: (entities: Array<FileSystemEntity>) => any, onError?: (error: any) => any);
}
public getEntities(onSuccess: (entities: Array<FileSystemEntity>) => any, onError?: (error) => any);
/**
Enumerates all the top-level FileSystem entities residing within this folder.
The first parameter is a callback that receives the current entity.
If the callback returns false this will mean for the iteration to stop.
*/
public eachEntity(onEntity: (entity: FileSystemEntity) => boolean, onError?: (error: any) => any);
}
/**
* Provides access to the top-level Folders instances that are accessible from the application. Use these as entry points to access the FileSystem.

View File

@ -64,9 +64,9 @@ export class FileSystemEntity {
}
/**
* Deletes the current entity from the file system.
* Removes the current entity from the file system.
*/
public delete(onSuccess?: () => any, onError?: (error: any) => any) {
public remove(onSuccess?: () => any, onError?: (error: any) => any) {
if (this instanceof File) {
getFileAccess().deleteFile(this.path, onSuccess, onError);
} else if (this instanceof Folder) {
@ -233,25 +233,21 @@ export class Folder extends FileSystemEntity {
/**
* Checks whether this Folder contains a file with the specified name.
*/
public containsFile(name: string): boolean {
public contains(name: string): boolean {
var fileAccess = getFileAccess();
var path = fileAccess.concatPath(this.path, name);
return fileAccess.fileExists(path);
}
/**
* Checks whether this Folder contains a Folder with the specified name.
*/
public containsFolder(name: string): boolean {
var fileAccess = getFileAccess();
var path = fileAccess.concatPath(this.path, name);
if (fileAccess.fileExists(path)) {
return true;
}
return fileAccess.folderExists(path);
}
/**
* Deletes all the files and folders (recursively), contained within this Folder.
* Removes all the files and folders (recursively), contained within this Folder.
*/
public empty(onSuccess?: () => any, onError?: (error: any) => any) {
public clear(onSuccess?: () => any, onError?: (error: any) => any) {
getFileAccess().emptyFolder(this.path, onSuccess, onError);
}
@ -295,7 +291,7 @@ export class Folder extends FileSystemEntity {
/**
* Gets all the top-level FileSystem entities residing within this Folder.
*/
public enumEntities(onSuccess: (files: Array<FileSystemEntity>) => any, onError?: (error: any) => any) {
public getEntities(onSuccess: (files: Array<FileSystemEntity>) => any, onError?: (error: any) => any) {
var localSuccess = function (fileInfos: Array<{ path: string; name: string; extension: string }>) {
if (onSuccess) {
var entities = new Array<FileSystemEntity>();
@ -314,7 +310,30 @@ export class Folder extends FileSystemEntity {
onSuccess(entities);
}
}
getFileAccess().enumFiles(this.path, localSuccess, onError);
getFileAccess().getEntities(this.path, localSuccess, onError);
}
/**
Enumerates all the top-level FileSystem entities residing within this folder.
The first parameter is a callback that receives the current entity.
If the callback returns false this will mean for the iteration to stop.
*/
public eachEntity(onEntity: (entity: FileSystemEntity) => boolean, onError?: (error: any) => any) {
if (!onEntity) {
return;
}
var localSuccess = function (fileInfo: { path: string; name: string; extension: string }): boolean {
var entity;
if (fileInfo.extension) {
entity = createFile(fileInfo);
} else {
entity = createFolder(fileInfo);
}
return onEntity(entity);
}
getFileAccess().eachEntity(this.path, localSuccess, onError);
}
}

View File

@ -40,48 +40,38 @@ export class FileSystemAccess {
return { path: dirInfo.path, name: dirInfo.name };
}
public enumFiles(path: string, onSuccess: (files: Array<{ path: string; name: string; extension: string }>) => any, onError?: (error: any) => any) {
try {
var javaFile = new java.io.File(path);
if (!javaFile.getCanonicalFile().isDirectory()) {
if (onError) {
onError("There is no folder existing at path " + path);
}
public eachEntity(path: string, onEntity: (file: { path: string; name: string; extension: string }) => boolean, onError?: (error: any) => any) {
if (!onEntity) {
return;
}
return;
}
this.enumEntities(path, onEntity, onError);
}
var filesList: any = javaFile.listFiles();
var fileInfos = new Array<{ path: string; name: string; extension: string }>();
public getEntities(path: string, onSuccess: (files: Array<{ path: string; name: string; extension: string }>) => any, onError?: (error: any) => any) {
if (!onSuccess) {
return;
}
var length = filesList.length,
i,
filePath,
info;
var fileInfos = new Array<{ path: string; name: string; extension: string }>();
var onEntity = function (entity: { path: string; name: string; extension: string }): boolean {
fileInfos.push(entity);
return true;
}
for (i = 0; i < length; i++) {
javaFile = filesList[i];
info = {
path: javaFile.getAbsolutePath(),
name: javaFile.getName()
};
if (javaFile.isFile()) {
info.extension = this.getFileExtension(info.path);
}
fileInfos.push(info);
}
if (onSuccess) {
onSuccess(fileInfos);
}
} catch (exception) {
var errorOccurred;
var localError = function (error: any) {
if (onError) {
onError(exception);
onError(error);
}
errorOccurred = true;
}
this.enumEntities(path, onEntity, localError);
if (!errorOccurred) {
onSuccess(fileInfos);
}
}
@ -346,13 +336,56 @@ export class FileSystemAccess {
}
}
// TODO: This method is the same as in the iOS implementation.
// Make it in a separate file / module so it can be reused from both implementations.
private getFileExtension(path: string): string {
var dotIndex = path.lastIndexOf(".");
if (dotIndex && dotIndex >= 0 && dotIndex < path.length) {
// return the extension without the "." (like in iOS)
return path.substring(dotIndex + 1);
return path.substring(dotIndex);
}
return undefined;
return "";
}
private enumEntities(path: string, callback: (entity: { path: string; name: string; extension: string }) => boolean, onError?: (error) => any) {
try {
var javaFile = new java.io.File(path);
if (!javaFile.getCanonicalFile().isDirectory()) {
if (onError) {
onError("There is no folder existing at path " + path);
}
return;
}
var filesList = javaFile.listFiles();
var length = filesList.length,
i,
filePath,
info,
retVal;
for (i = 0; i < length; i++) {
javaFile = filesList[i];
info = {
path: javaFile.getAbsolutePath(),
name: javaFile.getName()
};
if (javaFile.isFile()) {
info.extension = this.getFileExtension(info.path);
}
retVal = callback(info);
if (retVal != undefined && !retVal) {
break;
}
}
} catch (exception) {
if (onError) {
onError(exception);
}
}
}
}

View File

@ -7,7 +7,10 @@ export declare class FileSystemAccess {
getParent(path: string, onError?: (error: any) => any): { path: string; name: string };
getFile(path: string, onError?: (error: any) => any): { path: string; name: string; extension: string };
getFolder(path: string, onError?: (error: any) => any): { path: string; name: string };
enumFiles(path: string, onSuccess: (files: Array<{ path: string; name: string; extension: string }>) => any, onError?: (error: any) => any);
getEntities(path: string, onSuccess: (files: Array<{ path: string; name: string; extension: string }>) => any, onError?: (error: any) => any);
eachEntity(path: string, onSuccess: (entity: { path: string; name: string; extension: string }) => boolean, onError?: (error: any) => any);
fileExists(path: string): boolean;
folderExists(path: string): boolean;
concatPath(left: string, right: string): string;

View File

@ -114,48 +114,38 @@ export class FileSystemAccess {
}
}
public enumFiles(path: string, onSuccess: (files: Array<{ path: string; name: string; extension: string }>) => any, onError?: (error: any) => any) {
try {
var fileManager = Foundation.NSFileManager.defaultManager();
var files = fileManager.contentsOfDirectoryAtPathError(path, null);
if (!files) {
if (onError) {
onError(new Error("Failed to enum files for forlder '" + path + "'"));
}
return;
}
var fileInfos = new Array<{ path: string; name: string; extension: string }>();
var file,
i,
info;
for (i = 0; i < files.count(); i++) {
file = files.objectAtIndex(i);
info = {
path: this.concatPath(path, file),
name: file
};
if (!this.folderExists(file)) {
info.extension = this.getFileExtension(info.path);
}
fileInfos.push(info);
}
if (onSuccess) {
onSuccess(fileInfos);
}
public eachEntity(path: string, onEntity: (file: { path: string; name: string; extension: string }) => any, onError?: (error: any) => any) {
if (!onEntity) {
return;
}
catch (ex) {
this.enumEntities(path, onEntity, onError);
}
public getEntities(path: string, onSuccess: (files: Array<{ path: string; name: string; extension: string }>) => any, onError?: (error: any) => any) {
if (!onSuccess) {
return;
}
var fileInfos = new Array<{ path: string; name: string; extension: string }>();
var onEntity = function (entity: { path: string; name: string; extension: string }): boolean {
fileInfos.push(entity);
return true;
}
var errorOccurred;
var localError = function (error: any) {
if (onError) {
onError(ex);
onError(error);
}
errorOccurred = true;
}
this.enumEntities(path, onEntity, onError);
if (!errorOccurred) {
onSuccess(fileInfos);
}
}
@ -213,7 +203,7 @@ export class FileSystemAccess {
}
}
this.enumFiles(path, filesEnum, onError);
this.getEntities(path, filesEnum, onError);
}
public rename(path: string, newPath: string, onSuccess?: () => any, onError?: (error: any) => any) {
@ -267,9 +257,24 @@ export class FileSystemAccess {
return url.path();
}
// TODO: This method is the same as in the iOS implementation.
// Make it in a separate file / module so it can be reused from both implementations.
private getFileExtension(path: string): string {
var url = Foundation.NSURL.fileURLWithPathIsDirectory(path, false);
return url.pathExtension();
// TODO [For Panata]: The definitions currently specify "any" as a return value of this method
//var nsString = Foundation.NSString.stringWithString(path);
//var extension = nsString.pathExtension();
//if (extension && extension.length > 0) {
// extension = extension.concat(".", extension);
//}
//return extension;
var dotIndex = path.lastIndexOf(".");
if (dotIndex && dotIndex >= 0 && dotIndex < path.length) {
return path.substring(dotIndex);
}
return "";
}
private deleteEntity(path: string, onSuccess?: () => any, onError?: (error: any) => any) {
@ -284,4 +289,50 @@ export class FileSystemAccess {
}
}
}
private enumEntities(path: string, callback: (entity: { path: string; name: string; extension: string }) => boolean, onError?: (error) => any) {
try {
var fileManager = Foundation.NSFileManager.defaultManager();
var files = fileManager.contentsOfDirectoryAtPathError(path, null);
if (!files) {
if (onError) {
onError(new Error("Failed to enum files for forlder '" + path + "'"));
}
return;
}
var fileInfos = new Array<{ path: string; name: string; extension: string }>();
var file,
i,
info,
retVal;
for (i = 0; i < files.count(); i++) {
file = files.objectAtIndex(i);
info = {
path: this.concatPath(path, file),
name: file
};
if (!this.folderExists(file)) {
info.extension = this.getFileExtension(info.path);
}
retVal = callback(info);
if (retVal != undefined && !retVal) {
// the callback returned false meaning we should stop the iteration
break;
}
}
}
catch (ex) {
if (onError) {
onError(ex);
}
}
}
}