/* ************************************************************************ # # DivConq # # http://divconq.com/ # # Copyright: # Copyright 2014 eTimeline, LLC. All rights reserved. # # License: # See the license.txt file in the project's top-level directory for details. # # Authors: # * Andy White # ************************************************************************ */ package divconq.filestore.local; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import divconq.filestore.CommonPath; import divconq.filestore.FileCollection; import divconq.filestore.IFileStoreFile; import divconq.filestore.IFileStoreScanner; import divconq.hub.Hub; import divconq.lang.op.FuncCallback; import divconq.lang.op.OperationContext; import divconq.struct.Struct; /** * Eventually we may shift to a "yield" approach, for now collects all files * * @author andy * */ public class FileSystemScanner extends FileCollection implements IFileStoreScanner { protected FileSystemDriver driver = null; protected FileSystemFile folder = null; public FileSystemScanner() { if (OperationContext.get().getSchema() != null) this.setType(Hub.instance.getSchema().getType("dciFileSystemScanner")); } public FileSystemScanner(FileSystemDriver driver) { this(); this.driver = driver; this.basePath = driver.resolvePath(CommonPath.ROOT); } public FileSystemScanner(FileSystemFile folder) { this(); this.driver = folder.driver(); this.folder = folder; this.basePath = folder.path(); } public void collectAll() { // don't collect more than once if (this.collection != null) return; this.collection = new ArrayList<>(); // TODO support filters/sorting/etc Path folder = (this.folder == null) ? this.driver.localPath() : this.folder.localPath(); // collect all for now...may be more efficient later try { Files.walkFileTree(folder, new SimpleFileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path sfolder, BasicFileAttributes attrs) throws IOException { if (!sfolder.equals(folder)) FileSystemScanner.this.collection.add(new FileSystemFile(FileSystemScanner.this.driver, sfolder)); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path sfile, BasicFileAttributes attrs) throws IOException { FileSystemScanner.this.collection.add(new FileSystemFile(FileSystemScanner.this.driver, sfile)); return FileVisitResult.CONTINUE; } }); } catch (IOException x) { OperationContext.get().error("Unable to walk directory: " + folder + ", error: " + x); } } @Override public void next(FuncCallback<IFileStoreFile> callback) { if (this.collection == null) this.collectAll(); super.next(callback); } @Override public void forEach(FuncCallback<IFileStoreFile> callback) { if (this.collection == null) this.collectAll(); super.forEach(callback); } // TODO change to lazy stream /* TODO @Override public Iterable<Struct> getItems() { if (this.driver == null) return null; String cwd = this.driver.getFieldAsString("RootFolder"); Boolean recursive = this.getFieldAsBoolean("Recursive"); ListStruct match = this.getFieldAsList("MatchFiles"); List<String> wildcards = new ArrayList<String>(); if (match != null) for (Struct s : match.getItems()) wildcards.add(((StringStruct)s).getValue()); // see AndFileFilter and OrFileFilter IOFileFilter filefilter = new WildcardFileFilter(wildcards); // TODO support more options, size/date, folder filter return new Matches(new File(cwd), filefilter, ((recursive != null) && recursive) ? TrueFileFilter.TRUE : FalseFileFilter.FALSE); * / return null; } // TODO consider using Path instead of File public class Matches implements Iterable<Struct>, Iterator<Struct> { protected Iterator<File> itr = null; /* TODO public Matches(File folder, IOFileFilter filefilter, IOFileFilter folderfilter) { this.itr = FileUtils.iterateFiles(folder, filefilter, folderfilter); } * / @Override public Iterator<Struct> iterator() { return this; } @Override public boolean hasNext() { return this.itr.hasNext(); } @Override public Struct next() { return new FileSystemFile(FileSystemScanner.this.driver, this.itr.next().toPath()); } @Override public void remove() { this.itr.remove(); } } */ @Override protected void doCopy(Struct n) { super.doCopy(n); FileSystemScanner nn = (FileSystemScanner)n; nn.driver = this.driver; } @Override public Struct deepCopy() { FileSystemScanner cp = new FileSystemScanner(); this.doCopy(cp); return cp; } }