package er.extensions.foundation; import java.io.File; import java.util.UUID; import com.webobjects.foundation.NSMutableDictionary; /** * Allows you to store a large amount of files and folders without the hassles * of directory size limitations. The files are stored by an abstract * "key" which is by default a {@link UUID}. * <p> * It uses a factory to create the folder structure under the root * directory. With the default factory there will be directories for the first * two characters and under these again directories for the next two characters * of the GUID. * * @author ak (original version by Dominik Westner) * */ public class ERXFileRepository { protected File _root; protected final Factory _factory; /** * Private constructor, as we use the factory methods to create instances. * @param root * @param factory */ protected ERXFileRepository(File root, Factory factory) { _root = root; _factory = factory; } /** * Returns a new file in the repository. As you can also create directories * it does not really create the file, only the path to the file. You can * use file.getName() to get at the GUID which is the key to the file. * @return the new file */ public File createFile() { return getFile(UUID.randomUUID().toString()); } /** * Returns a file for a given id * @param id the id of the file * @return a file for the given id */ public File getFile(String id) { return new File(_factory.getDir(getRoot(), id), id); } /** * Returns true if the file is present in the repository and also exists. * @param id the id of the file * @return true if the file exists in the repository */ public boolean hasFile(String id) { return getFile(id).exists(); } /** * Returns the root directory for the repository. * @return the root directory for the repository */ public File getRoot() { return _root; } /** * Holds the repositories. */ private static final NSMutableDictionary _repositories = ERXMutableDictionary.synchronizedDictionary(); /** * Returns the repository that is registered under the given name. * @param name the name under which the repository is registered * @return the repository that is registered under the given name or null */ public static ERXFileRepository repository(String name) { return (ERXFileRepository) _repositories.objectForKey(name); } /** * Adds a repository under the given name and the given root directory that uses the default factory. * @param name the name under which the repository should be added * @param root the root directory of the repository * @return the new repository */ public static ERXFileRepository addRepository(String name, File root) { return addRepository(name, new ERXFileRepository(root, new DefaultFactory())); } /** * Adds a repository under the given name and the given root directory that uses the given factory. * @param name the name under which the repository should be added * @param root the root directory of the repository * @param factory the factory to determine the directory from the id for this repository * @return the new repository */ public static ERXFileRepository addRepository(String name, File root, Factory factory) { return addRepository(name, new ERXFileRepository(root, factory)); } /** * Adds an existing repository under the given name. * @param name the name under which the repository should be added * @param repository the repository to register * @return the repository */ public static ERXFileRepository addRepository(String name, ERXFileRepository repository) { _repositories.setObjectForKey(repository, name); return repository; } public static interface Factory { public File getDir(File root, String id); } /** Default implementation of the Factory interface. */ public static class DefaultFactory implements Factory { /** * Returns a parent dir for a given ID. Will create the * directory if it doesn't exist. * @param root * @param id */ public File getDir(File root, String id) { File dir = new File(root, id.substring(0, 2) + File.separator + id.substring(2, 4)); if (!dir.exists()) { dir.mkdirs(); } return dir; } } }