diff --git a/buildsystem/dependencies.gradle b/buildsystem/dependencies.gradle index 1b329a81..9d527cc4 100644 --- a/buildsystem/dependencies.gradle +++ b/buildsystem/dependencies.gradle @@ -58,7 +58,7 @@ ext.versions = [ // Testing. junit : '4.12', assertJ : '1.7.1', - mockito : '1.9.5', + mockito : '2.8.9', robolectric : '3.1.2', supportTestRunner : '0.4.1', espresso : '2.2.1', diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/FSAllEraser.java b/filesystem/src/main/java/com/nytimes/android/external/fs3/FSAllEraser.java deleted file mode 100644 index cd9d8c41..00000000 --- a/filesystem/src/main/java/com/nytimes/android/external/fs3/FSAllEraser.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.nytimes.android.external.fs3; - -import com.nytimes.android.external.fs3.filesystem.FileSystem; -import com.nytimes.android.external.store3.base.DiskAllErase; - -import java.util.concurrent.Callable; - -import javax.annotation.Nonnull; - -import io.reactivex.Observable; - - -public class FSAllEraser implements DiskAllErase { - final FileSystem fileSystem; - - public FSAllEraser(FileSystem fileSystem) { - this.fileSystem = fileSystem; - } - @Nonnull - @Override - public Observable deleteAll(@Nonnull final String path) { - return Observable.fromCallable(new Callable() { - @Nonnull - @Override - @SuppressWarnings("PMD.SignatureDeclareThrowsException") - public Boolean call() throws Exception { - fileSystem.deleteAll(path); - return true; - } - }); - } -} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/FSAllEraser.kt b/filesystem/src/main/java/com/nytimes/android/external/fs3/FSAllEraser.kt new file mode 100644 index 00000000..93ecc5d8 --- /dev/null +++ b/filesystem/src/main/java/com/nytimes/android/external/fs3/FSAllEraser.kt @@ -0,0 +1,13 @@ +package com.nytimes.android.external.fs3 + +import com.nytimes.android.external.fs3.filesystem.FileSystem +import com.nytimes.android.external.store3.base.DiskAllErase +import io.reactivex.Observable + + +class FSAllEraser(private val fileSystem: FileSystem) : DiskAllErase { + override fun deleteAll(path: String): Observable = Observable.fromCallable { + fileSystem.deleteAll(path) + true + } +} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/FSWriter.java b/filesystem/src/main/java/com/nytimes/android/external/fs3/FSWriter.java deleted file mode 100644 index 8b4eb506..00000000 --- a/filesystem/src/main/java/com/nytimes/android/external/fs3/FSWriter.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.nytimes.android.external.fs3; - -import com.nytimes.android.external.fs3.filesystem.FileSystem; -import com.nytimes.android.external.store3.base.DiskWrite; - -import javax.annotation.Nonnull; - -import io.reactivex.Single; -import okio.BufferedSource; - -/** - * FSReader is used when persisting to file system - * PathResolver will be used in creating file system paths based on cache keys. - * Make sure to have keys containing same data resolve to same "path" - * @param key type - */ -public class FSWriter implements DiskWrite { - final FileSystem fileSystem; - final PathResolver pathResolver; - - public FSWriter(FileSystem fileSystem, PathResolver pathResolver) { - this.fileSystem = fileSystem; - this.pathResolver = pathResolver; - } - - @Nonnull - @Override - public Single write(@Nonnull final T key, @Nonnull final BufferedSource data) { - return Single.fromCallable(() -> { - fileSystem.write(pathResolver.resolve(key), data); - return true; - }); - } -} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/FSWriter.kt b/filesystem/src/main/java/com/nytimes/android/external/fs3/FSWriter.kt new file mode 100644 index 00000000..0b2afe1d --- /dev/null +++ b/filesystem/src/main/java/com/nytimes/android/external/fs3/FSWriter.kt @@ -0,0 +1,21 @@ +package com.nytimes.android.external.fs3 + +import com.nytimes.android.external.fs3.filesystem.FileSystem +import com.nytimes.android.external.store3.base.DiskWrite + +import io.reactivex.Single +import okio.BufferedSource + +/** + * FSReader is used when persisting to file system + * PathResolver will be used in creating file system paths based on cache keys. + * Make sure to have keys containing same data resolve to same "path" + * @param key type + */ +open class FSWriter(private val fileSystem: FileSystem, internal val pathResolver: PathResolver) : DiskWrite { + + override fun write(key: T, data: BufferedSource): Single = Single.fromCallable { + fileSystem.write(pathResolver.resolve(key), data) + true + } +} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/RecordPersister.java b/filesystem/src/main/java/com/nytimes/android/external/fs3/RecordPersister.java deleted file mode 100644 index a318d344..00000000 --- a/filesystem/src/main/java/com/nytimes/android/external/fs3/RecordPersister.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.nytimes.android.external.fs3; - -import com.nytimes.android.external.fs3.filesystem.FileSystem; -import com.nytimes.android.external.store3.base.RecordProvider; -import com.nytimes.android.external.store3.base.RecordState; -import com.nytimes.android.external.store3.base.impl.BarCode; - -import java.util.concurrent.TimeUnit; - -import javax.annotation.Nonnull; -import javax.inject.Inject; - -public class RecordPersister extends SourcePersister implements RecordProvider { - - @Nonnull - private final TimeUnit expirationUnit; - private final long expirationDuration; - - @Inject - public RecordPersister(FileSystem fileSystem, - long expirationDuration, - @Nonnull TimeUnit expirationUnit) { - super(fileSystem); - this.expirationDuration = expirationDuration; - this.expirationUnit = expirationUnit; - } - - public static RecordPersister create(FileSystem fileSystem, - long expirationDuration, - @Nonnull TimeUnit expirationUnit) { - return new RecordPersister(fileSystem, expirationDuration, expirationUnit); - } - - @Nonnull - @Override - public RecordState getRecordState(@Nonnull BarCode barCode) { - return sourceFileReader.getRecordState(barCode, expirationUnit, expirationDuration); - } -} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/RecordPersister.kt b/filesystem/src/main/java/com/nytimes/android/external/fs3/RecordPersister.kt new file mode 100644 index 00000000..41bee099 --- /dev/null +++ b/filesystem/src/main/java/com/nytimes/android/external/fs3/RecordPersister.kt @@ -0,0 +1,24 @@ +package com.nytimes.android.external.fs3 + +import com.nytimes.android.external.fs3.filesystem.FileSystem +import com.nytimes.android.external.store3.base.RecordProvider +import com.nytimes.android.external.store3.base.RecordState +import com.nytimes.android.external.store3.base.impl.BarCode + +import java.util.concurrent.TimeUnit +import javax.inject.Inject + +class RecordPersister @Inject +constructor(fileSystem: FileSystem, + private val expirationDuration: Long, + private val expirationUnit: TimeUnit) : SourcePersister(fileSystem), RecordProvider { + + override fun getRecordState(barCode: BarCode): RecordState = sourceFileReader.getRecordState(barCode, expirationUnit, expirationDuration) + + companion object { + + fun create(fileSystem: FileSystem, + expirationDuration: Long, + expirationUnit: TimeUnit): RecordPersister = RecordPersister(fileSystem, expirationDuration, expirationUnit) + } +} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceAllPersister.java b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceAllPersister.java deleted file mode 100644 index 2c55fc83..00000000 --- a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceAllPersister.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.nytimes.android.external.fs3; - - -import com.nytimes.android.external.fs3.filesystem.FileSystem; -import com.nytimes.android.external.store3.base.AllPersister; -import com.nytimes.android.external.store3.base.impl.BarCode; - -import java.io.FileNotFoundException; - -import javax.annotation.Nonnull; -import javax.inject.Inject; - -import io.reactivex.Maybe; -import io.reactivex.Observable; -import io.reactivex.Single; -import okio.BufferedSource; - -public class SourceAllPersister implements AllPersister { - - @Nonnull - final FSAllReader sourceFileAllReader; - @Nonnull - final FSAllEraser sourceFileAllEraser; - - @Nonnull - final FSReader sourceFileReader; - @Nonnull - final FSWriter sourceFileWriter; - - @Inject - public SourceAllPersister(FileSystem fileSystem) { - sourceFileAllReader = new FSAllReader(fileSystem); - sourceFileAllEraser = new FSAllEraser(fileSystem); - sourceFileReader = new FSReader<>(fileSystem, new BarCodeReadAllPathResolver()); - sourceFileWriter = new FSWriter<>(fileSystem, new BarCodeReadAllPathResolver()); - } - - @Nonnull - @Override - public Observable readAll(@Nonnull final String path) throws FileNotFoundException { - return sourceFileAllReader.readAll(path); - } - - @Nonnull - @Override - public Observable deleteAll(@Nonnull final String path) { - return sourceFileAllEraser.deleteAll(path); - } - - @Nonnull - @Override - public Maybe read(@Nonnull BarCode barCode) { - return sourceFileReader.read(barCode); - } - - @Nonnull - @Override - public Single write(@Nonnull BarCode barCode, @Nonnull BufferedSource data) { - return sourceFileWriter.write(barCode, data); - } - - public static SourceAllPersister create(FileSystem fileSystem) { - return new SourceAllPersister(fileSystem); - } -} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceAllPersister.kt b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceAllPersister.kt new file mode 100644 index 00000000..02c1889f --- /dev/null +++ b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceAllPersister.kt @@ -0,0 +1,40 @@ +package com.nytimes.android.external.fs3 + + +import com.nytimes.android.external.fs3.filesystem.FileSystem +import com.nytimes.android.external.store3.base.AllPersister +import com.nytimes.android.external.store3.base.impl.BarCode + +import java.io.FileNotFoundException +import javax.inject.Inject + +import io.reactivex.Maybe +import io.reactivex.Observable +import io.reactivex.Single +import okio.BufferedSource + +class SourceAllPersister @Inject +constructor(fileSystem: FileSystem) : AllPersister { + + private val sourceFileAllReader: FSAllReader by lazy { FSAllReader(fileSystem) } + private val sourceFileAllEraser: FSAllEraser by lazy { FSAllEraser(fileSystem) } + + private val sourceFileReader: FSReader by lazy { FSReader(fileSystem, BarCodeReadAllPathResolver()) } + private val sourceFileWriter: FSWriter by lazy { FSWriter(fileSystem, BarCodeReadAllPathResolver()) } + + @Throws(FileNotFoundException::class) + override fun readAll(path: String): Observable = sourceFileAllReader.readAll(path) + + override fun deleteAll(path: String): Observable = sourceFileAllEraser.deleteAll(path) + + override fun read(barCode: BarCode): Maybe = sourceFileReader.read(barCode) + + override fun write(barCode: BarCode, data: BufferedSource): Single = sourceFileWriter.write(barCode, data) + + companion object { + + fun create(fileSystem: FileSystem): SourceAllPersister { + return SourceAllPersister(fileSystem) + } + } +} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileReader.java b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileReader.java deleted file mode 100644 index 0952a95e..00000000 --- a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileReader.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.nytimes.android.external.fs3; - -import com.nytimes.android.external.fs3.filesystem.FileSystem; -import com.nytimes.android.external.store3.base.DiskRead; -import com.nytimes.android.external.store3.base.RecordState; -import com.nytimes.android.external.store3.base.impl.BarCode; - -import java.util.concurrent.TimeUnit; - -import javax.annotation.Nonnull; - -import okio.BufferedSource; - -import static com.nytimes.android.external.fs3.SourcePersister.pathForBarcode; - -public class SourceFileReader extends FSReader implements DiskRead { - - public SourceFileReader(FileSystem fileSystem) { - this(fileSystem, new BarCodePathResolver()); - } - - public SourceFileReader(FileSystem fileSystem, PathResolver pathResolver) { - super(fileSystem, pathResolver); - } - - @Nonnull - public RecordState getRecordState(@Nonnull BarCode barCode, - @Nonnull TimeUnit expirationUnit, - long expirationDuration) { - return fileSystem.getRecordState(expirationUnit, expirationDuration, pathForBarcode(barCode)); - } -} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileReader.kt b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileReader.kt new file mode 100644 index 00000000..2110b8e0 --- /dev/null +++ b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileReader.kt @@ -0,0 +1,15 @@ +package com.nytimes.android.external.fs3 + +import com.nytimes.android.external.fs3.filesystem.FileSystem +import com.nytimes.android.external.store3.base.DiskRead +import com.nytimes.android.external.store3.base.RecordState +import com.nytimes.android.external.store3.base.impl.BarCode +import okio.BufferedSource +import java.util.concurrent.TimeUnit + +class SourceFileReader @JvmOverloads constructor(fileSystem: FileSystem, pathResolver: PathResolver = BarCodePathResolver()) : FSReader(fileSystem, pathResolver), DiskRead { + + fun getRecordState(barCode: BarCode, + expirationUnit: TimeUnit, + expirationDuration: Long): RecordState = fileSystem.getRecordState(expirationUnit, expirationDuration, SourcePersister.pathForBarcode(barCode)) +} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileWriter.java b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileWriter.java deleted file mode 100644 index 3a225a70..00000000 --- a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileWriter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.nytimes.android.external.fs3; - -import com.nytimes.android.external.fs3.filesystem.FileSystem; -import com.nytimes.android.external.store3.base.DiskWrite; -import com.nytimes.android.external.store3.base.impl.BarCode; - -import okio.BufferedSource; - -public class SourceFileWriter extends FSWriter implements DiskWrite { - - public SourceFileWriter(FileSystem fileSystem) { - this(fileSystem, new BarCodePathResolver()); - } - - public SourceFileWriter(FileSystem fileSystem, PathResolver pathResolver) { - super(fileSystem, pathResolver); - } - -} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileWriter.kt b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileWriter.kt new file mode 100644 index 00000000..3dc2a17b --- /dev/null +++ b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourceFileWriter.kt @@ -0,0 +1,9 @@ +package com.nytimes.android.external.fs3 + +import com.nytimes.android.external.fs3.filesystem.FileSystem +import com.nytimes.android.external.store3.base.DiskWrite +import com.nytimes.android.external.store3.base.impl.BarCode + +import okio.BufferedSource + +class SourceFileWriter @JvmOverloads constructor(fileSystem: FileSystem, pathResolver: PathResolver = BarCodePathResolver()) : FSWriter(fileSystem, pathResolver), DiskWrite diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourcePersister.java b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourcePersister.java deleted file mode 100644 index 789f752c..00000000 --- a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourcePersister.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.nytimes.android.external.fs3; - - -import com.nytimes.android.external.fs3.filesystem.FileSystem; -import com.nytimes.android.external.store3.base.Persister; -import com.nytimes.android.external.store3.base.impl.BarCode; - -import javax.annotation.Nonnull; -import javax.inject.Inject; - -import io.reactivex.Maybe; -import io.reactivex.Single; -import okio.BufferedSource; - -/** - * Persister to be used when storing something to persister from a BufferedSource - * example usage: - * ParsingStoreBuilder.builder() - * .fetcher(fetcher) - * .persister(new SourcePersister(fileSystem)) - * .parser(new GsonSourceParser<>(gson, BookResults.class)) - * .open(); - */ -public class SourcePersister implements Persister { - - @Nonnull - final SourceFileReader sourceFileReader; - @Nonnull - final SourceFileWriter sourceFileWriter; - - @Inject - public SourcePersister(FileSystem fileSystem) { - sourceFileReader = new SourceFileReader(fileSystem); - sourceFileWriter = new SourceFileWriter(fileSystem); - } - - public static SourcePersister create(FileSystem fileSystem) { - return new SourcePersister(fileSystem); - } - - @Nonnull - static String pathForBarcode(@Nonnull BarCode barCode) { - return barCode.getType() + barCode.getKey(); - } - - @Nonnull - @Override - public Maybe read(@Nonnull final BarCode barCode) { - return sourceFileReader.read(barCode); - } - - @Nonnull - @Override - public Single write(@Nonnull final BarCode barCode, @Nonnull final BufferedSource data) { - return sourceFileWriter.write(barCode, data); - } - -} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourcePersister.kt b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourcePersister.kt new file mode 100644 index 00000000..48c0f7c0 --- /dev/null +++ b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourcePersister.kt @@ -0,0 +1,38 @@ +package com.nytimes.android.external.fs3 + + +import com.nytimes.android.external.fs3.filesystem.FileSystem +import com.nytimes.android.external.store3.base.Persister +import com.nytimes.android.external.store3.base.impl.BarCode +import javax.inject.Inject + +import io.reactivex.Maybe +import io.reactivex.Single +import okio.BufferedSource + +/** + * Persister to be used when storing something to persister from a BufferedSource + * example usage: + * ParsingStoreBuilder., BookResults>builder() + * .fetcher(fetcher) + * .persister(new SourcePersister(fileSystem)) + * .parser(new GsonSourceParser<>(gson, BookResults.class)) + * .open(); + */ +open class SourcePersister @Inject +constructor(fileSystem: FileSystem) : Persister { + + internal val sourceFileReader: SourceFileReader by lazy { SourceFileReader(fileSystem) } + internal val sourceFileWriter: SourceFileWriter by lazy { SourceFileWriter(fileSystem)} + + override fun read(barCode: BarCode): Maybe = sourceFileReader.read(barCode) + + override fun write(barCode: BarCode, data: BufferedSource): Single = sourceFileWriter.write(barCode, data) + + companion object { + + fun create(fileSystem: FileSystem): SourcePersister = SourcePersister(fileSystem) + + internal fun pathForBarcode(barCode: BarCode): String = barCode.type + barCode.key + } +} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourcePersisterFactory.java b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourcePersisterFactory.java index 03a2aecf..6018de83 100644 --- a/filesystem/src/main/java/com/nytimes/android/external/fs3/SourcePersisterFactory.java +++ b/filesystem/src/main/java/com/nytimes/android/external/fs3/SourcePersisterFactory.java @@ -35,7 +35,7 @@ public static Persister create(@Nonnull File root, if (root == null) { throw new IllegalArgumentException("root file cannot be null."); } - return RecordPersister.create(FileSystemFactory.create(root), expirationDuration, expirationUnit); + return RecordPersister.Companion.create(FileSystemFactory.create(root), expirationDuration, expirationUnit); } /** @@ -49,7 +49,7 @@ public static Persister create(@Nonnull FileSystem file if (fileSystem == null) { throw new IllegalArgumentException("fileSystem cannot be null."); } - return RecordPersister.create(fileSystem, expirationDuration, expirationUnit); + return RecordPersister.Companion.create(fileSystem, expirationDuration, expirationUnit); } /** @@ -63,7 +63,7 @@ public static Persister create(@Nonnull File root) thro if (root == null) { throw new IllegalArgumentException("root file cannot be null."); } - return SourcePersister.create(FileSystemFactory.create(root)); + return SourcePersister.Companion.create(FileSystemFactory.create(root)); } /** @@ -75,7 +75,7 @@ public static Persister create(@Nonnull FileSystem file if (fileSystem == null) { throw new IllegalArgumentException("fileSystem cannot be null."); } - return SourcePersister.create(fileSystem); + return SourcePersister.Companion.create(fileSystem); } /** @@ -89,7 +89,7 @@ public static Persister createAll(@Nonnull File root) t if (root == null) { throw new IllegalArgumentException("root file cannot be null."); } - return SourceAllPersister.create(FileSystemFactory.create(root)); + return SourceAllPersister.Companion.create(FileSystemFactory.create(root)); } /** @@ -101,6 +101,6 @@ public static Persister createAll(@Nonnull FileSystem f if (fileSystem == null) { throw new IllegalArgumentException("fileSystem cannot be null."); } - return SourceAllPersister.create(fileSystem); + return SourceAllPersister.Companion.create(fileSystem); } } diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/Util.java b/filesystem/src/main/java/com/nytimes/android/external/fs3/Util.java deleted file mode 100644 index 472f8512..00000000 --- a/filesystem/src/main/java/com/nytimes/android/external/fs3/Util.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.nytimes.android.external.fs3; - - -import java.io.File; -import java.io.IOException; -import java.util.Stack; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class Util { - - @Nonnull - public String simplifyPath(@Nonnull String path) { - if (ifInvalidPATH(path)) { - return ""; - } - - String delim = "[/]+"; - String[] arr = path.split(delim); - - Stack stack = new Stack<>(); - - fillStack(arr, stack); - - if (emptyStack(stack)) { - return "/"; - } - - StringBuilder sb = new StringBuilder(); - - for (String str : stack) { - sb.append("/").append(str); - } - - return sb.toString(); - } - - private boolean emptyStack(@Nonnull Stack stack) { - return stack.isEmpty(); - } - - private void fillStack(@Nonnull String[] arr, @Nonnull Stack stack) { - for (String str : arr) { - if ("/".equals(str)) { - continue; - } - if ("..".equals(str)) { - if (!stack.isEmpty()) { - stack.pop(); - } - } else if (!".".equals(str) && !str.isEmpty()) { - stack.push(str); - } - } - } - - private boolean ifInvalidPATH(@Nullable String path) { - return path == null || path.length() == 0; - } - - public void createParentDirs(@Nonnull File file) throws IOException { - File parent = file.getCanonicalFile().getParentFile(); - if (parent == null) { - /* - * The given directory is a filesystem root. All zero of its ancestors - * exist. This doesn't mean that the root itself exists -- consider x:\ on - * a Windows machine without such a drive -- or even that the caller can - * create it, but this method makes no such guarantees even for non-root - * files. - */ - return; - } - parent.mkdirs(); - if (!parent.isDirectory()) { - throw new IOException("Unable to create parent directories of " + file); - } - } -} diff --git a/filesystem/src/main/java/com/nytimes/android/external/fs3/Util.kt b/filesystem/src/main/java/com/nytimes/android/external/fs3/Util.kt new file mode 100644 index 00000000..6f400a0a --- /dev/null +++ b/filesystem/src/main/java/com/nytimes/android/external/fs3/Util.kt @@ -0,0 +1,73 @@ +package com.nytimes.android.external.fs3 + + +import java.io.File +import java.io.IOException +import java.util.Stack + +class Util { + + fun simplifyPath(path: String): String { + if (ifInvalidPATH(path)) { + return "" + } + + val delim = "[/]+" + val arr = path.split(delim.toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + val stack = Stack() + + fillStack(arr, stack) + + if (emptyStack(stack)) { + return "/" + } + + val sb = StringBuilder() + + for (str in stack) { + sb.append("/").append(str) + } + + return sb.toString() + } + + private fun emptyStack(stack: Stack): Boolean { + return stack.isEmpty() + } + + private fun fillStack(arr: Array, stack: Stack) { + for (str in arr) { + if ("/" == str) { + continue + } + if (".." == str) { + if (!stack.isEmpty()) { + stack.pop() + } + } else if ("." != str && !str.isEmpty()) { + stack.push(str) + } + } + } + + private fun ifInvalidPATH(path: String?): Boolean { + return path == null || path.length == 0 + } + + @Throws(IOException::class) + fun createParentDirs(file: File) { + val parent = file.canonicalFile.parentFile + ?: /* + * The given directory is a filesystem root. All zero of its ancestors + * exist. This doesn't mean that the root itself exists -- consider x:\ on + * a Windows machine without such a drive -- or even that the caller can + * create it, but this method makes no such guarantees even for non-root + * files. + */ + return + parent.mkdirs() + if (!parent.isDirectory) { + throw IOException("Unable to create parent directories of $file") + } + } +} diff --git a/filesystem/src/test/java/com/nytimes/android/external/fs3/StoreNetworkBeforeStaleTest.kt b/filesystem/src/test/java/com/nytimes/android/external/fs3/StoreNetworkBeforeStaleTest.kt index 207a0eb2..c2b82334 100644 --- a/filesystem/src/test/java/com/nytimes/android/external/fs3/StoreNetworkBeforeStaleTest.kt +++ b/filesystem/src/test/java/com/nytimes/android/external/fs3/StoreNetworkBeforeStaleTest.kt @@ -50,9 +50,6 @@ class StoreNetworkBeforeStaleTest { .thenReturn(Maybe.just(disk1)) //get should return from disk `when`(persister.getRecordState(barCode)).thenReturn(RecordState.STALE) - `when`(persister.write(barCode, network1)) - .thenReturn(Single.just(true)) - store.get(barCode).test().awaitTerminalEvent() val inOrder = inOrder(fetcher, persister) @@ -106,9 +103,6 @@ class StoreNetworkBeforeStaleTest { // empty, second call after network should return the network value `when`(persister.getRecordState(barCode)).thenReturn(RecordState.MISSING) - `when`(persister.write(barCode, network1)) - .thenReturn(Single.just(true)) - store.get(barCode).test().assertError(sorry) val inOrder = inOrder(fetcher, persister) diff --git a/filesystem/src/test/java/com/nytimes/android/external/fs3/StoreRefreshWhenStaleTest.kt b/filesystem/src/test/java/com/nytimes/android/external/fs3/StoreRefreshWhenStaleTest.kt index cf2e7b3a..78587905 100644 --- a/filesystem/src/test/java/com/nytimes/android/external/fs3/StoreRefreshWhenStaleTest.kt +++ b/filesystem/src/test/java/com/nytimes/android/external/fs3/StoreRefreshWhenStaleTest.kt @@ -68,16 +68,11 @@ class StoreRefreshWhenStaleTest { @Test fun diskWasNotRefreshedWhenFreshRecord() { - `when`(fetcher.fetch(barCode)) - .thenReturn(Single.just(network1)) `when`(persister.read(barCode)) .thenReturn(Maybe.just(disk1)) //get should return from disk .thenReturn(Maybe.just(disk2)) //backfill should read from disk again `when`(persister.getRecordState(barCode)).thenReturn(RecordState.FRESH) - `when`(persister.write(barCode, network1)) - .thenReturn(Single.just(true)) - var testObserver: TestObserver = store .get(barCode) .test() diff --git a/filesystem/src/test/java/com/nytimes/android/external/fs3/filesystem/FSFileTest.kt b/filesystem/src/test/java/com/nytimes/android/external/fs3/filesystem/FSFileTest.kt index c7b5fb32..3463acf5 100644 --- a/filesystem/src/test/java/com/nytimes/android/external/fs3/filesystem/FSFileTest.kt +++ b/filesystem/src/test/java/com/nytimes/android/external/fs3/filesystem/FSFileTest.kt @@ -6,8 +6,7 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder -import org.mockito.Matchers.any -import org.mockito.Matchers.anyByte +import org.mockito.ArgumentMatchers import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.verify @@ -36,7 +35,7 @@ class FSFileTest { @Test @Throws(IOException::class) fun closeSourceAfterWrite() { - `when`(source.read(any(Buffer::class.java), anyByte().toLong())).thenReturn(java.lang.Long.valueOf(-1)) + `when`(source.read(ArgumentMatchers.any(Buffer::class.java), ArgumentMatchers.anyLong())).thenReturn(-1L) fsFile.write(source) verify(source).close() } diff --git a/filesystem/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/filesystem/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 00000000..ca6ee9ce --- /dev/null +++ b/filesystem/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline \ No newline at end of file diff --git a/store/src/test/java/com/nytimes/android/external/store3/ClearStoreTest.kt b/store/src/test/java/com/nytimes/android/external/store3/ClearStoreTest.kt index dd053308..ecee109f 100644 --- a/store/src/test/java/com/nytimes/android/external/store3/ClearStoreTest.kt +++ b/store/src/test/java/com/nytimes/android/external/store3/ClearStoreTest.kt @@ -65,7 +65,6 @@ class ClearStoreTest { .thenReturn(Maybe.empty()) //read from disk after clearing disk cache .thenReturn(Maybe.just(1)) //read from disk after making additional network call `when`(persister.write(barcode1, 1)).thenReturn(Single.just(true)) - `when`(persister.write(barcode1, 2)).thenReturn(Single.just(true)) `when`(persister.read(barcode2)) .thenReturn(Maybe.empty()) //read from disk @@ -73,7 +72,6 @@ class ClearStoreTest { .thenReturn(Maybe.empty()) //read from disk after clearing disk cache .thenReturn(Maybe.just(1)) //read from disk after making additional network call - `when`(persister.write(barcode2, 1)).thenReturn(Single.just(true)) `when`(persister.write(barcode2, 2)).thenReturn(Single.just(true)) // each request should produce one call diff --git a/store/src/test/java/com/nytimes/android/external/store3/GetRefreshingTest.java b/store/src/test/java/com/nytimes/android/external/store3/GetRefreshingTest.java index 94d788f5..b6ca707a 100644 --- a/store/src/test/java/com/nytimes/android/external/store3/GetRefreshingTest.java +++ b/store/src/test/java/com/nytimes/android/external/store3/GetRefreshingTest.java @@ -71,7 +71,6 @@ public void testRefreshOnClearAll() { .thenReturn(Maybe.empty()) //read from disk after clearing disk cache .thenReturn(Maybe.just(1)); //read from disk after making additional network call when(persister.write(barcode1, 1)).thenReturn(Single.just(true)); - when(persister.write(barcode1, 2)).thenReturn(Single.just(true)); when(persister.read(barcode2)) .thenReturn(Maybe.empty()) //read from disk @@ -79,7 +78,6 @@ public void testRefreshOnClearAll() { .thenReturn(Maybe.empty()) //read from disk after clearing disk cache .thenReturn(Maybe.just(1)); //read from disk after making additional network call - when(persister.write(barcode2, 1)).thenReturn(Single.just(true)); when(persister.write(barcode2, 2)).thenReturn(Single.just(true)); TestObserver testObservable1 = store.getRefreshing(barcode1).test();