diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryLoaderTask.java b/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryLoaderTask.java index e57340d8..455bbbdb 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryLoaderTask.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryLoaderTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -188,7 +188,7 @@ protected void addItem(DirectoryBuilder builder, String path, int markerItemCoun } private void compressLatLon(IDirectory result) { - IDirectory[] children = (result != null) ? result.getChildren() : null; + IDirectory[] children = (result != null) ? result.getChildDirs() : null; if (children != null) { for (IDirectory _child: children) { diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorFragment.java b/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorFragment.java index a7507391..434ed4e5 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorFragment.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -744,7 +744,7 @@ private void reloadDirGuiIfAvailable(String why) { // scroll to right where deepest child is if (first != null) mParentPathBarScroller.requestChildFocus(mParentPathBar, first); - IDirectory[] children = selectedChild.getChildren(); + IDirectory[] children = selectedChild.getChildDirs(); if (children != null) { for (IDirectory child : children) { Button button = createPathButton(child); diff --git a/app/src/main/java/de/k3b/android/util/OsUtils.java b/app/src/main/java/de/k3b/android/util/OsUtils.java index 8d35f50a..714fae20 100644 --- a/app/src/main/java/de/k3b/android/util/OsUtils.java +++ b/app/src/main/java/de/k3b/android/util/OsUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder. * @@ -88,7 +88,7 @@ public static OSDirectory getRootOSDirectory(OSDirectory factory) { OSDirectory rootDir = createOsDirectory( FileFacade.convert(context + 1, "/"), factory); - if (rootDir.getChildren() == null || rootDir.getChildren().length == 0) { + if (rootDir.getChildDirs(null) == null || rootDir.getChildDirs(null).length == 0) { // load on demand has failed on non rooted device // externalStorageFile diff --git a/fotolib2/src/main/java/de/k3b/io/AlbumFile.java b/fotolib2/src/main/java/de/k3b/io/AlbumFile.java index f9046656..0ce22f7d 100644 --- a/fotolib2/src/main/java/de/k3b/io/AlbumFile.java +++ b/fotolib2/src/main/java/de/k3b/io/AlbumFile.java @@ -22,6 +22,8 @@ import java.util.ArrayList; import java.util.List; +import de.k3b.io.filefacade.FileFacade; + /** * Created by k3b on 17.04.2018. */ @@ -30,6 +32,14 @@ public class AlbumFile { public static final String SUFFIX_VALBUM = ".album"; public static final String SUFFIX_QUERY = ".query"; + static { + init(); + } + + public static void init() { + FileFacade.includeFileSuffixesForListDir(SUFFIX_QUERY, SUFFIX_VALBUM); + } + public static boolean isQueryFile(String uri) { if (uri != null) { return isQueryFile(uri, SUFFIX_VALBUM) || isQueryFile(uri, SUFFIX_QUERY); diff --git a/fotolib2/src/main/java/de/k3b/io/Directory.java b/fotolib2/src/main/java/de/k3b/io/Directory.java index dc9a3f0f..96af26ba 100644 --- a/fotolib2/src/main/java/de/k3b/io/Directory.java +++ b/fotolib2/src/main/java/de/k3b/io/Directory.java @@ -64,7 +64,7 @@ public Directory(String relPath, IDirectory parent, int nonDirItemCount) { setNonDirItemCount(nonDirItemCount); } - public static IDirectory[] removeChild(IDirectory parent, IDirectory[] children, IDirectory... child) { + public static T[] removeChild(IDirectory parent, T[] children, T... child) { List positions = new ArrayList<>(); for (int i = 0; i < child.length; i++) { int index = parent.childIndexOf(child[i]); @@ -72,23 +72,12 @@ public static IDirectory[] removeChild(IDirectory parent, IDirectory[] children, positions.add(index); } } - return removeChild(children, positions); + return removeChild(parent, children, positions); } - @Override - public void destroy() { - if (children != null) { - for (IDirectory child : getChildren()) { - child.destroy(); - } - children = null; - } - parent = null; - } - - public static IDirectory[] removeChild(IDirectory[] children, List removePositions) { + public static T[] removeChild(IDirectory factory, T[] children, List removePositions) { if (removePositions != null && removePositions.size() > 0) { - IDirectory[] newArray = new IDirectory[children.length - removePositions.size()]; + T[] newArray = factory.createOsDirectoryArray(children.length - removePositions.size()); int in = children.length; int out = newArray.length; while (--in >= 0) { @@ -101,17 +90,22 @@ public static IDirectory[] removeChild(IDirectory[] children, List remo return children; } - public static IDirectory[] add(IDirectory[] oldChildren, IDirectory... newChildren) { + public static T[] add(IDirectory factory, T[] oldChildren, T... newChildren) { if (newChildren == null || newChildren.length == 0) return oldChildren; if (oldChildren == null || oldChildren.length == 0) return newChildren; - IDirectory[] result = new IDirectory[newChildren.length + oldChildren.length]; + T[] result = factory.createOsDirectoryArray(newChildren.length + oldChildren.length); System.arraycopy(oldChildren, 0, result, 0, oldChildren.length); System.arraycopy(newChildren, 0, result, oldChildren.length, newChildren.length); return result; } + public static int getChildCount(IDirectory item) { + if ((item != null) && (item.getChildDirs() != null)) return item.getChildDirs().length; + return 0; + } + public static int childIndexOf(T[] children, T child) { if (child != null && children != null) { for (int i = children.length - 1; i >= 0; i--) { @@ -121,16 +115,68 @@ public static int childIndexOf(T[] children, T child) { return -1; } - public static int getChildCount(IDirectory item) { - if ((item != null) && (item.getChildren() != null)) return item.getChildren().length; - return 0; + protected static StringBuilder toTreeString(StringBuilder result, Directory item, String delimiter, int options) { + if (item != null) { + result.append(item.getRelPath()); + appendCount(result, item, options); + result.append(delimiter); + + if (item.getChildDirs() != null) { + for (IDirectory child : item.getChildDirs()) { + toTreeString(result, (Directory) child, delimiter, options); + } + } + } + return result; + } + + private static IDirectory find(IDirectory parent, StringBuilder path) { + while (path.indexOf(PATH_DELIMITER) == 0) { + path.delete(0, PATH_DELIMITER.length()); + } + + int pathLen = path.length(); + if (pathLen == 0) return parent; + + if (parent.getChildDirs() != null) { + for (IDirectory child : parent.getChildDirs()) { + if (path.indexOf(child.getRelPath()) == 0) { + int childLen = child.getRelPath().length(); + if (childLen == pathLen) return child; // found last path element + int end = path.indexOf(PATH_DELIMITER, childLen); + + if (end == childLen) { + path.delete(0, childLen); + return find(child, path); + } + } + } + } + + return null; + } + + @Override + public void destroy() { + if (children != null) { + for (IDirectory child : getChildDirs()) { + child.destroy(); + } + children = null; + } + parent = null; + } + + @Override + public void removeChild(IDirectory... child) { + children = Directory.removeChild(this, children, child); } /** * factory method to be overwrittern by derived classes, if tree should consist of derived classes. */ @Override - public IDirectory createOsDirectory(IFile file, IDirectory parent, IDirectory[] children) { + public Directory createOsDirectory(IFile file, IDirectory parent, IDirectory[] children) { final Directory result = new Directory(file.getName(), parent, 0); if (children != null) { @@ -141,15 +187,6 @@ public IDirectory createOsDirectory(IFile file, IDirectory parent, IDirectory[] return result; } - @Override - public void removeChild(IDirectory... child) { - children = Directory.removeChild(this, children, child); - } - - public void addChild(IDirectory... child) { - this.children = add(this.children, child); - } - /*------------------- simple properties ------------------------*/ @Override @@ -182,9 +219,12 @@ public int childIndexOf(IDirectory child) { return childIndexOf(children, child); } + /** + * factory method to be overwrittern by derived classes. + */ @Override - public IDirectory[] getChildren() { - return children; + public Directory[] createOsDirectoryArray(int size) { + return new Directory[size]; } /*------------------- formatting ------------------------*/ @@ -205,19 +245,8 @@ public String getAbsolute() { return result.toString(); } - protected static StringBuilder toTreeString(StringBuilder result, Directory item, String delimiter, int options) { - if (item != null) { - result.append(item.getRelPath()); - appendCount(result, item, options); - result.append(delimiter); - - if (item.getChildren() != null) { - for (IDirectory child : item.getChildren()) { - toTreeString(result, (Directory) child, delimiter, options); - } - } - } - return result; + public void addChild(IDirectory... child) { + this.children = add(this, this.children, child); } public static void appendCount(StringBuilder result, IDirectory _item, int options) { @@ -307,30 +336,9 @@ public IDirectory find(String path) { return null; } - private static IDirectory find(IDirectory parent, StringBuilder path) { - while (path.indexOf(PATH_DELIMITER) == 0) { - path.delete(0, PATH_DELIMITER.length()); - } - - int pathLen = path.length(); - if (pathLen == 0) return parent; - - if (parent.getChildren() != null) { - for(IDirectory child : parent.getChildren()) { - if (path.indexOf(child.getRelPath()) == 0) { - int childLen = child.getRelPath().length(); - if (childLen == pathLen) return child; // found last path element - int end = path.indexOf(PATH_DELIMITER, childLen); - - if (end == childLen) { - path.delete(0,childLen); - return find(child, path); - } - } - } - } - - return null; + @Override + public IDirectory[] getChildDirs() { + return children; } @Override diff --git a/fotolib2/src/main/java/de/k3b/io/DirectoryBuilder.java b/fotolib2/src/main/java/de/k3b/io/DirectoryBuilder.java index 4dab4aff..0fa3c488 100644 --- a/fotolib2/src/main/java/de/k3b/io/DirectoryBuilder.java +++ b/fotolib2/src/main/java/de/k3b/io/DirectoryBuilder.java @@ -36,7 +36,8 @@ public DirectoryBuilder() { } private static List getChildren(Directory dir) { - return (dir != null && dir.getChildren() != null) ? Arrays.asList(dir.getChildren()) : null; + IDirectory[] childDirs = (dir != null) ? dir.getChildDirs() : null; + return (childDirs != null) ? Arrays.asList(childDirs) : null; } public static void createStatistics(List children) { @@ -98,7 +99,7 @@ private Directory mergeDirWithChildIfPossible(Directory firstChild) { firstChild.setRelPath(firstChild.getRelPath() + Directory.PATH_DELIMITER + child.getRelPath()); firstChild.setNonDirItemCount(firstChild.getNonDirItemCount() + child.getNonDirItemCount()); - firstChild.setChildren(child.getChildren()); + firstChild.setChildren(child.getChildDirs()); child.setParent(null); child.setChildren(null); diff --git a/fotolib2/src/main/java/de/k3b/io/DirectoryNavigator.java b/fotolib2/src/main/java/de/k3b/io/DirectoryNavigator.java index 8a7a9894..688bda82 100644 --- a/fotolib2/src/main/java/de/k3b/io/DirectoryNavigator.java +++ b/fotolib2/src/main/java/de/k3b/io/DirectoryNavigator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager * @@ -72,7 +72,7 @@ public IDirectory getChild(int groupIndex, int childIndex) { "): index must be 0 .. " + (Directory.getChildCount(group) - 1)); } - return group.getChildren()[childIndex]; + return group.getChildDirs()[childIndex]; } @Override @@ -84,7 +84,7 @@ public IDirectory getGroup(int groupIndex) { "): index must be 0 .. " + (getGroupCount() - 1)); } - return currentGrandFather.getChildren()[groupIndex]; + return currentGrandFather.getChildDirs()[groupIndex]; } public void setCurrentGrandFather(IDirectory currentGrandFather) { @@ -126,7 +126,7 @@ public IDirectory getSubChild(int... indexes) { IDirectory found = this.getRoot(); if (indexes != null) { for (int index : indexes) { - IDirectory[] children = (found != null) ? found.getChildren() : null; + IDirectory[] children = (found != null) ? found.getChildDirs() : null; int childCount = (children != null) ? children.length : 0; if ((index < 0) || (index >= childCount)) { return null; diff --git a/fotolib2/src/main/java/de/k3b/io/IDirectory.java b/fotolib2/src/main/java/de/k3b/io/IDirectory.java index 22c77d24..d70a7ac3 100644 --- a/fotolib2/src/main/java/de/k3b/io/IDirectory.java +++ b/fotolib2/src/main/java/de/k3b/io/IDirectory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder. * @@ -23,15 +23,15 @@ /** * Abstraction of Directory - * + *

* Created by k3b on 04.08.2015. */ -public interface IDirectory { - int DIR_FLAG_NONE = 0; - int DIR_FLAG_NOMEDIA = 1; // below linux hidden dir ".*" or below DIR_FLAG_NOMEDIA_ROOT - int DIR_FLAG_NOMEDIA_ROOT = 2; // containing ".nomedia" +public interface IDirectory { + int DIR_FLAG_NONE = 0; + int DIR_FLAG_NOMEDIA = 1; // below linux hidden dir ".*" or below DIR_FLAG_NOMEDIA_ROOT + int DIR_FLAG_NOMEDIA_ROOT = 2; // containing ".nomedia" - int DIR_FLAG_APM_DIR = 8; // containing ".apm" + int DIR_FLAG_APM_DIR = 8; // containing ".apm" int DIR_FLAG_VIRTUAL_DIR = 9; // containing "*.album" String APM_DIR_PREFIX = "ยง "; @@ -39,19 +39,21 @@ public interface IDirectory { String getAbsolute(); - IDirectory createOsDirectory(IFile file, IDirectory parent, IDirectory[] children); + T createOsDirectory(IFile file, T parent, T[] children); + + T[] createOsDirectoryArray(int size); - IDirectory getParent(); + T getParent(); - IDirectory[] getChildren(); + T[] getChildDirs(); - void removeChild(IDirectory... child); + void removeChild(T... child); - void addChild(IDirectory... child); + void addChild(T... child); int childIndexOf(IDirectory child); - IDirectory find(String path); + T find(String path); void destroy(); diff --git a/fotolib2/src/main/java/de/k3b/io/OSDirOrVirtualAlbumFile.java b/fotolib2/src/main/java/de/k3b/io/OSDirOrVirtualAlbumFile.java index 17823160..ef00d0ce 100644 --- a/fotolib2/src/main/java/de/k3b/io/OSDirOrVirtualAlbumFile.java +++ b/fotolib2/src/main/java/de/k3b/io/OSDirOrVirtualAlbumFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2020 by k3b. + * Copyright (c) 2018-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager * @@ -28,7 +28,7 @@ */ public class OSDirOrVirtualAlbumFile extends OSDirectory { - public OSDirOrVirtualAlbumFile(IFile current, OSDirectory parent, IDirectory[] childen) { + public OSDirOrVirtualAlbumFile(IFile current, OSDirectory parent, OSDirectory[] childen) { super(current, parent, childen); if (isAlbum(current)) { setDirFlags(DIR_FLAG_VIRTUAL_DIR); @@ -51,16 +51,16 @@ protected int getCalculateFlags(IFile directory) { } @Override - protected boolean isDirectory(IFile candidate) { - if (super.isDirectory(candidate)) return true; - return isAlbum(candidate); + protected boolean isDirectory(IFile file) { + if (super.isDirectory(file)) return true; + return isAlbum(file); } /** * factory method to be overwrittern by derived classes, if tree should consist of derived classes. */ @Override - public OSDirectory createOsDirectory(IFile file, IDirectory parent, IDirectory[] children) { - return new OSDirOrVirtualAlbumFile(file, (OSDirectory) parent, children); + public OSDirectory createOsDirectory(IFile file, OSDirectory parent, OSDirectory[] children) { + return new OSDirOrVirtualAlbumFile(file, parent, children); } } \ No newline at end of file diff --git a/fotolib2/src/main/java/de/k3b/io/OSDirectory.java b/fotolib2/src/main/java/de/k3b/io/OSDirectory.java index 46a83961..7bae3af8 100644 --- a/fotolib2/src/main/java/de/k3b/io/OSDirectory.java +++ b/fotolib2/src/main/java/de/k3b/io/OSDirectory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager * @@ -23,26 +23,21 @@ import org.slf4j.LoggerFactory; import java.io.File; -import java.util.ArrayList; -import java.util.List; import de.k3b.LibGlobal; +import de.k3b.io.filefacade.FileCache; +import de.k3b.io.filefacade.FileCacheItem; import de.k3b.io.filefacade.FileFacade; import de.k3b.io.filefacade.IFile; /** * Operating System Directory with load on demand - * + *

* Created by k3b on 04.08.2015. */ -public class OSDirectory implements IDirectory { +public class OSDirectory extends FileCacheItem implements IDirectory { private static final Logger logger = LoggerFactory.getLogger(LibGlobal.LOG_TAG); - private IFile mCurrent = null; - private IDirectory[] mChilden = null; - - private OSDirectory mParent = null; - private int mDirFlags = DIR_FLAG_NONE; /** @@ -50,39 +45,50 @@ public class OSDirectory implements IDirectory { */ private String virtualName = null; + private static final OsDirFileCache theCache = new OsDirFileCache(); + // protected constructor to allow unittesting with fake children - public OSDirectory(IFile current, OSDirectory parent, IDirectory[] childen) { - setCurrent(current); - mParent = parent; - mChilden = childen; + public OSDirectory(IFile current, OSDirectory parent, OSDirectory[] childen) { + super(current); + super.setParent(parent); + super.setChildDirs(childen); + if ((getDirFlags() == DIR_FLAG_NONE) - && (mParent != null) - && mParent.isDirFlagsNomedia()) { + && (getParent() != null) + && getParent().isDirFlagsNomedia()) { // inherit nomedia from parent setDirFlags(DIR_FLAG_NOMEDIA); } } + public static OsDirFileCache getTheCache() { + return theCache; + } + + public static void setTheCache(OsDirFileCache theCache) { + theCache = theCache; + } + // package to allow unit testing - protected static IDirectory find(OSDirectory root, String path) { + protected static OSDirectory find(OSDirectory root, String path) { return find(root, FileFacade.convert("OSDirectory find", path)); } // protected to allow unit testing - protected static IDirectory find(OSDirectory root, IFile file) { + protected static OSDirectory find(OSDirectory root, IFile file) { if (file == null) return null; - if (root.mCurrent.equals(file)) { + if (root.getCurrent().equals(file)) { return root; } OSDirectory provider = root.findViaFile(root, file); if (provider != null) return provider; - IDirectory parentDir = find(root, file.getParentFile()); + OSDirectory parentDir = find(root, file.getParentFile()); if (parentDir == null) return null; String name = file.getName(); - OSDirectory result = (OSDirectory) findChildByRelPath(parentDir.getChildren(), name); + OSDirectory result = (OSDirectory) findChildByRelPath(parentDir.getChildDirs(null), name); if (result == null) { result = root.createOsDirectory(file, parentDir, null); @@ -92,16 +98,38 @@ protected static IDirectory find(OSDirectory root, IFile file) { } public static IDirectory findChildByRelPath(IDirectory[] children, String name) { - for (IDirectory cur : children) { - if (name.equals(cur.getRelPath())) { - return cur; + if (children != null) { + for (IDirectory cur : children) { + if (name.equals(cur.getRelPath())) { + return cur; + } } } return null; } - protected IFile getCurrent() { - return mCurrent; + public static void toTreeString(StringBuffer result, String indent, IDirectory dir) { + result.append(indent).append(dir.getRelPath()).append("\n"); + + // avoid load on demand + IDirectory[] children = dir.getChildDirs(); + if (children != null) { + String childIndent = indent + "-"; + for (IDirectory child : children) { + toTreeString(result, childIndent, child); + } + } + } + + private static OSDirectory[] add(OSDirectory[] oldChildren, OSDirectory... newChildren) { + if (newChildren == null || newChildren.length == 0) return oldChildren; + if (oldChildren == null || oldChildren.length == 0) return newChildren; + + OSDirectory[] result = new OSDirectory[newChildren.length + oldChildren.length]; + System.arraycopy(oldChildren, 0, result, 0, oldChildren.length); + + System.arraycopy(newChildren, 0, result, oldChildren.length, newChildren.length); + return result; } /** @@ -109,32 +137,17 @@ protected IFile getCurrent() { */ @Override public void refresh() { - setDirFlags(getCalculateFlags(mCurrent)); + setDirFlags(getCalculateFlags(getCurrent())); } + @Override public OSDirectory setCurrent(IFile current) { + super.setCurrent(current); destroy(); - mCurrent = current; - setDirFlags(getCalculateFlags(mCurrent)); + setDirFlags(getCalculateFlags(getCurrent())); return this; } - @Override - public String getRelPath() { - if (this.virtualName != null) return this.virtualName; - return mCurrent.getName(); - } - - @Override - public String getAbsolute() { - return mCurrent.getAbsolutePath(); - } - - @Override - public IDirectory getParent() { - return mParent; - } - private OSDirectory getRoot() { IDirectory current = this; IDirectory parent = current.getParent(); @@ -162,110 +175,71 @@ protected int getCalculateFlags(IFile directory) { return result; } + @Override + public String getRelPath() { + if (this.virtualName != null) return this.virtualName; + return getCurrent().getName(); + } + + @Override + public String getAbsolute() { + return getCurrent().getAbsolutePath(); + } + /** * #114: update internal data after a folder has been renamed in the gui */ @Override public void rename(String oldFolderName, String newFolderName) { - this.mCurrent = mCurrent.getParentFile().create(newFolderName); - } - - public static void toTreeString(StringBuffer result, String indent, IDirectory dir) { - result.append(indent).append(dir.getRelPath()).append("\n"); - - // avoid load on demand - IDirectory[] mChilden = (dir instanceof OSDirectory) ? ((OSDirectory) dir).mChilden : dir.getChildren(); - if (mChilden != null) { - String childIndent = indent + "-"; - for (IDirectory child : mChilden) { - toTreeString(result, childIndent, child); - } - } + this.setCurrent(getCurrent().getParentFile().create(newFolderName)); } /** * factory method to be overwrittern by derived classes, if tree should consist of derived classes. */ @Override - public OSDirectory createOsDirectory(IFile file, IDirectory parent, IDirectory[] children) { + public OSDirectory createOsDirectory(IFile file, OSDirectory parent, OSDirectory[] children) { return new OSDirectory(file, (OSDirectory) parent, children); } + public OSDirectory[] createOsDirectoryArray(int size) { + return new OSDirectory[size]; + } + @Override - public IDirectory[] getChildren() { - if ((mCurrent != null) && (mChilden == null)) { - IFile[] files = mCurrent.listFiles(); - addChildDirs(files); - } - return mChilden; + public void destroy() { + // throw new IllegalStateException(); } @Override - public void removeChild(IDirectory... child) { - this.mChilden = Directory.removeChild(this, this.mChilden, child); + public void removeChild(OSDirectory... child) { + setChildDirs(Directory.removeChild(this, getChildDirs(), child)); } @Override - public void addChild(IDirectory... child) { - this.mChilden = Directory.add(this.mChilden, child); + public void addChild(OSDirectory... child) { + setChildDirs(add(getChildDirs(), child)); } @Override public int childIndexOf(IDirectory child) { - return Directory.childIndexOf(mChilden, child); + return Directory.childIndexOf(getChildDirs(), child); } protected boolean isDirectory(IFile file) { return file.isDirectory(); } - public void addChildDirs(IFile... files) { - if (files != null || files.length > 0) { - List newDirs = new ArrayList<>(); - - for (IFile file : files) { - if ((file != null) - && !file.isHidden() - && !file.getName().startsWith(".") - && !FileUtils.isSymlinkDir(file.getFile(), true) - // && file.canWrite() // bugfix: must be visible because writeprotected parentdir may contain writeenabled subdirs - ) { - if (isDirectory(file)) { - newDirs.add(createOsDirectory(file, this, null)); - } - } - } - if (mChilden != null) { - for (IDirectory old : mChilden) { - newDirs.add(old); - } - } - mChilden = newDirs.toArray(new IDirectory[newDirs.size()]); - } - } - @Override - public IDirectory find(String path) { + public OSDirectory find(String path) { if (path == null) return null; return find(FileFacade.convert("OSDirectory find ", path).getCanonicalFile()); } - protected IDirectory find(IFile file) { + protected OSDirectory find(IFile file) { return find(getRoot(), file); } - @Override - public void destroy() { - destroy(mChilden); - mChilden = null; - mCurrent = null; - mParent = null; - } - - public void addChildDirs(IDirectory... dirs) { - this.mChilden = Directory.add(mChilden, dirs); - } - @Override public int getSelectionIconID() { return 0; @@ -273,7 +247,7 @@ public int getSelectionIconID() { @Override public String toString() { - return mCurrent.toString(); + return getCurrent().toString(); } public String toTreeString() { @@ -297,14 +271,17 @@ public OSDirectory includeRoot(IFile file, OSDirectory factory) { if (factory == null) factory = this; OSDirectory result = factory.createOsDirectory(file, root, null); result.virtualName = file.getCanonicalPath(); - root.addChildDirs(result); + root.addChild(result); return result; } protected OSDirectory findViaFile(OSDirectory parentDir, IFile file) { - for (IDirectory candidate : parentDir.getChildren()) { - if (candidate.equals(file)) return (OSDirectory) candidate; + OSDirectory[] childDirs = (parentDir != null) ? parentDir.getChildDirs(null) : null; + if (childDirs != null) { + for (IDirectory candidate : childDirs) { + if (candidate.equals(file)) return (OSDirectory) candidate; + } } return null; } @@ -331,15 +308,15 @@ private OSDirectory addChildSubFolders(String... newCildFolderNames) { return current; } - private OSDirectory addChildFolder(String newCildFolderName, IDirectory[] grandChilden) { + private OSDirectory addChildFolder(String newCildFolderName, OSDirectory[] grandChilden) { OSDirectory result = null; - IDirectory[] children = this.getChildren(); + OSDirectory[] children = this.getChildDirs(null); File newRelativeChild = new File(newCildFolderName); if (!newRelativeChild.isAbsolute()) { result = (OSDirectory) findChildByRelPath(children, newCildFolderName); if (result == null) { - IFile newChildFile = mCurrent.create(newCildFolderName).getCanonicalFile(); + IFile newChildFile = getCurrent().create(newCildFolderName).getCanonicalFile(); result = createOsDirectory(newChildFile, this, grandChilden); if (result != null) { this.addChild(result); @@ -351,8 +328,9 @@ private OSDirectory addChildFolder(String newCildFolderName, IDirectory[] grandC @Override public boolean equals(Object o) { - if (o instanceof OSDirectory) return this.mCurrent.equals(((OSDirectory) o).mCurrent); - if (o instanceof IFile) return this.mCurrent.equals(o); + if (o instanceof OSDirectory) + return this.getCurrent().equals(((OSDirectory) o).getCurrent()); + if (o instanceof IFile) return this.getCurrent().equals(o); return super.equals(o); } @@ -361,7 +339,7 @@ public boolean equals(Object o) { * @return false if path cannot be created. **/ public boolean osMkDirs() { - return mCurrent.mkdirs() || mCurrent.isDirectory(); + return getCurrent().mkdirs() || getCurrent().isDirectory(); } @Override @@ -374,6 +352,26 @@ public void setDirFlags(int dirFlags) { } public boolean isDirFlagsNomedia() { - return (this.getDirFlags() & (DIR_FLAG_NOMEDIA | DIR_FLAG_NOMEDIA_ROOT)) != DIR_FLAG_NONE; - } + return (this.getDirFlags() & (DIR_FLAG_NOMEDIA | DIR_FLAG_NOMEDIA_ROOT)) != DIR_FLAG_NONE; + } + + @Override + public OSDirectory[] getChildDirs() { + return getChildDirs(theCache); + } + + + public static class OsDirFileCache extends FileCache { + @Override + public OSDirectory create(IFile file) { + return new OSDirectory(file, null, null); + } + + @Override + public OSDirectory[] create(int size) { + return new OSDirectory[0]; + } + + } + } diff --git a/fotolib2/src/test/java/de/k3b/io/DirectoryTests.java b/fotolib2/src/test/java/de/k3b/io/DirectoryTests.java index 7dab0e98..49794f8a 100644 --- a/fotolib2/src/test/java/de/k3b/io/DirectoryTests.java +++ b/fotolib2/src/test/java/de/k3b/io/DirectoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder. * @@ -30,14 +30,14 @@ public class DirectoryTests { public void shoudChildIndexOf() { IDirectory root = createDirsABC(); - Assert.assertEquals(1, root.childIndexOf(root.getChildren()[1])); + Assert.assertEquals(1, root.childIndexOf(root.getChildDirs()[1])); } @Test public void shoudRemoveChild() { IDirectory root = createDirsABC(); - root.removeChild(root.getChildren()[1], null); + root.removeChild(root.getChildDirs()[1], null); assertTree("x(3)|a|c|", root); } @@ -55,7 +55,7 @@ private IDirectory createDirsABC() { directoryBuilder.add("/x/a", 0, 0); directoryBuilder.add("/x/b", 0, 0); directoryBuilder.add("/x/c", 0, 0); - IDirectory root = directoryBuilder.getRoot().getChildren()[0]; + IDirectory root = directoryBuilder.getRoot().getChildDirs()[0]; assertTree("x(3)|a|b|c|", root); return root; } @@ -71,7 +71,7 @@ public void shoudGetAbsolute() { public void shoudCompress() { DirectoryBuilder builder = new DirectoryBuilder(); builder.add("/a/b/c/", 0, 0); - IDirectory result = builder.getRoot().getChildren()[0]; + IDirectory result = builder.getRoot().getChildDirs()[0]; Assert.assertEquals("a/b/c", result.getRelPath()); } @@ -81,7 +81,7 @@ public void shouldCalculateStatistics() { builder.add("/a/b", 1, 0); builder.add("/a/b/c",2, 0); builder.add("/a/b/c/d",4, 0); - IDirectory root = builder.getRoot().getChildren()[0]; + IDirectory root = builder.getRoot().getChildDirs()[0]; assertTree("a/b(1+1):(1+6)|c(1):(2+4)|d:(4)|", root); } @@ -95,7 +95,7 @@ public void noAddShoudbeEmpty() { public void shoudBuild1() { DirectoryBuilder builder = new DirectoryBuilder(); builder.add("/a/b/c/", 0, 0); - IDirectory root = builder.getRoot().getChildren()[0]; + IDirectory root = builder.getRoot().getChildDirs()[0]; Assert.assertEquals("/a/b/c", root.getAbsolute()); } @@ -105,7 +105,7 @@ public void shoudBuildDirPlus2Children() { builder.add("/a/b", 0, 0); builder.add("/a/b/c1", 0, 0); builder.add("/a/b/c2", 0, 0); - IDirectory root = builder.getRoot().getChildren()[0]; + IDirectory root = builder.getRoot().getChildDirs()[0]; assertTree("a/b(2)|c1|c2|", root); } @@ -114,7 +114,7 @@ public void siblingsShoudSplit() { DirectoryBuilder builder = new DirectoryBuilder(); builder.add("/a/b/c1", 0, 0); builder.add("/a/b/c2", 0, 0); - IDirectory root = builder.getRoot().getChildren()[0]; + IDirectory root = builder.getRoot().getChildDirs()[0]; assertTree("a/b(2)|c1|c2|", root); } @@ -122,7 +122,7 @@ public void siblingsShoudSplit() { public void shoudSetNonDirItemCount() { DirectoryBuilder builder = new DirectoryBuilder(); builder.add("/a/b/c", 4, 0); - Directory root = (Directory) builder.getRoot().getChildren()[0]; + Directory root = (Directory) builder.getRoot().getChildDirs()[0]; Assert.assertEquals(4, root.getNonDirItemCount()); } @@ -131,7 +131,7 @@ public void shoudAddNonDirItemCount() { DirectoryBuilder builder = new DirectoryBuilder(); builder.add("/a/b/c", 4, 0); builder.add("/a/b/c", 3, 0); - Directory root = (Directory) builder.getRoot().getChildren()[0]; + Directory root = (Directory) builder.getRoot().getChildDirs()[0]; Assert.assertEquals(7, root.getNonDirItemCount()); } diff --git a/fotolib2/src/test/java/de/k3b/io/OSDirectoryTests.java b/fotolib2/src/test/java/de/k3b/io/OSDirectoryTests.java index 01c869d9..ff5b826c 100644 --- a/fotolib2/src/test/java/de/k3b/io/OSDirectoryTests.java +++ b/fotolib2/src/test/java/de/k3b/io/OSDirectoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 by k3b. + * Copyright (c) 2015-2021 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -47,8 +47,8 @@ public void setup() { public void shoudFindExisting() { IDirectory found = OSDirectory.find(mRoot, "a/b/c"); assertNotNull(found); - assertEquals(1, found.getChildren().length); - assertEquals("d", found.getChildren()[0].getRelPath()); + assertEquals(1, found.getChildDirs().length); + assertEquals("d", found.getChildDirs()[0].getRelPath()); } @Test @@ -68,8 +68,8 @@ public void shoudFindExistingWithRoot() { out.println(mRoot.toTreeString()); assertNotNull(found); - assertEquals(1, found.getChildren().length); - assertEquals("d", found.getChildren()[0].getRelPath()); + assertEquals(1, found.getChildDirs().length); + assertEquals("d", found.getChildDirs()[0].getRelPath()); } @Test @@ -99,18 +99,18 @@ public void shoudAddDirWithSub() { @Test public void shoudFindNewWithRoot() { mRoot = createTestData("/", "a/b/c/d"); - int rootLen = (mRoot.getChildren() == null) ? 0 : mRoot.getChildren().length; + int rootLen = (mRoot.getChildDirs(null) == null) ? 0 : mRoot.getChildDirs(null).length; IDirectory found = OSDirectory.find(mRoot, "/q"); out.println(mRoot.toTreeString()); assertNotNull(found); - assertEquals(rootLen + 1, mRoot.getChildren().length); + assertEquals(rootLen + 1, mRoot.getChildDirs(null).length); } @Test public void shoudFindNew() { IDirectory found = OSDirectory.find(mRoot, "a/b/c/d2").getParent(); - assertEquals(2, found.getChildren().length); + assertEquals(2, found.getChildDirs().length); } @Test @@ -132,7 +132,7 @@ public void shoudGetParent() { @Test public void shoudGetChildren() { - assertEquals(true, mRoot.getChildren().length > 0); + assertEquals(true, mRoot.getChildDirs(null).length > 0); } @Test @@ -146,8 +146,8 @@ public void shoudHandleRoot() { OSDirectory rootDir = new OSDirectory(rootFile, null, null); rootDir.includeRoot(new FileFacade(new File("/storage/emulated/0")), null); rootDir.includeRoot(new FileFacade(new File("/storage/1234-5678")), null); - assertEquals("#", 2, rootDir.getChildren().length); - assertEquals("path endsWith('1234-5678')", true, rootDir.getChildren()[1].getRelPath().endsWith("1234-5678")); + assertEquals("#", 2, rootDir.getChildDirs(null).length); + assertEquals("path endsWith('1234-5678')", true, rootDir.getChildDirs(null)[1].getRelPath().endsWith("1234-5678")); } @Ignore("https://stackoverflow.com/questions/48710003/how-to-make-this-junit-test-for-java-memory-leak-pass") @@ -181,7 +181,8 @@ public void shoudNotMemoryLeak() { private OSDirectory createTestData(String rootName, String elements) { final IFile file = FileFacade.convert("OSDirectoryTests create test data", rootName); - OSDirectory root = new OSDirectory(file, null, null); + // new OSDirectory[0] prevents load on demand + OSDirectory root = new OSDirectory(file, null, new OSDirectory[0]); root.addChildFolder(elements); return root; } diff --git a/libK3bFilefacade/src/main/java/de/k3b/io/filefacade/FileFacade.java b/libK3bFilefacade/src/main/java/de/k3b/io/filefacade/FileFacade.java index 15f6276a..0700c5ec 100644 --- a/libK3bFilefacade/src/main/java/de/k3b/io/filefacade/FileFacade.java +++ b/libK3bFilefacade/src/main/java/de/k3b/io/filefacade/FileFacade.java @@ -270,10 +270,13 @@ public static boolean accept(String nameLowerCase) { public IFile[] listDirs() { List found = new ArrayList<>(); - for (File file : file.listFiles()) { - if (file != null && - (file.isDirectory() || accept(file.getName().toLowerCase()))) { - found.add(convert(null, file)); + File[] files = (file != null) ? file.listFiles() : null; + if (files != null) { + for (File file : files) { + if (file != null && + (file.isDirectory() || accept(file.getName().toLowerCase()))) { + found.add(convert(null, file)); + } } } return found.toArray(new IFile[found.size()]);