Skip to content
This repository has been archived by the owner on Aug 9, 2020. It is now read-only.

Decouple gson #39

Merged
merged 4 commits into from
Jun 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,27 @@ allprojects {
And add next dependencies in the build.gradle of the module:
```gradle
dependencies {
compile "com.github.VictorAlbertos.RxCache:core:1.4.8"
compile "com.github.VictorAlbertos.RxCache:core:1.5.0"
compile "io.reactivex:rxjava:1.1.5"
}
```

Because RxCache uses internally [Jolyglot](https://github.com/VictorAlbertos/Jolyglot) to serialize and deserialize objects, you need to add the next dependency to gradle in case you want RxCache uses Gson as its json library.
```gradle
dependencies {
compile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.1'
}
```

If you prefer that RxCache uses Jackson, add this other dependency:
```gradle
dependencies {
compile 'com.github.VictorAlbertos.Jolyglot:jackson:0.0.1'
}
```

Moshi is not supported for now.

## Usage

Define an `interface` with as much methods as needed to create the caching providers:
Expand Down Expand Up @@ -94,7 +110,7 @@ Finally, instantiate the Providers `interface` using `RxCache.Builder` and suppl
```java
File cacheDir = getFilesDir();
Providers providers = new RxCache.Builder()
.persistence(cacheDir)
.persistence(cacheDir, new GsonSpeaker())
.using(Providers.class);
```

Expand All @@ -116,7 +132,7 @@ public class Repository {

public Repository(File cacheDir) {
providers = new RxCache.Builder()
.persistence(cacheDir)
.persistence(cacheDir, new GsonSpeaker())
.using(Providers.class);
}

Expand All @@ -140,14 +156,12 @@ public class Repository {
}
```


## Use cases

* Using classic API RxCache for read actions with little write needs.
* Using actionable API RxCache, exclusive for write actions.


## Classic API RxCache:

Following use cases illustrate some common scenarios which will help to understand the usage of `DynamicKey` and `DynamicKeyGroup` classes along with evicting scopes.

### List
Expand Down Expand Up @@ -255,7 +269,7 @@ apply plugin: 'com.neenbedankt.android-apt'

dependencies {
// apt command comes from the android-apt plugin
apt "com.github.VictorAlbertos.RxCache:compiler:1.4.8"
apt "com.github.VictorAlbertos.RxCache:compiler:1.5.0"
}
```

Expand Down Expand Up @@ -444,7 +458,7 @@ You can check an [example](https://github.com/VictorAlbertos/RxCacheSamples/blob
RxCache serves the data from one of its three layers:

* A memory layer -> Powered by [Apache ReferenceMap](https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/map/ReferenceMap.html).
* A persisting layer -> RxCache uses internally [Gson](https://github.com/google/gson) for serialize and deserialize objects.
* A persisting layer -> RxCache uses internally [Jolyglot](https://github.com/VictorAlbertos/Jolyglot) for serialize and deserialize objects.
* A loader layer (the observable supplied by the client library)

The policy is very simple:
Expand Down
1 change: 1 addition & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile project(':core')
apt project(':compiler')
compile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.1'

testCompile 'junit:junit:4.12'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.List;

import io.rx_cache.internal.RxCache;
import io.victoralbertos.jolyglot.GsonSpeaker;
import rx.Observable;

/**
Expand All @@ -22,7 +23,7 @@ public class MainActivity extends Activity {

final RxProviders rxProviders = new RxCache.Builder()
.setMaxMBPersistenceCache(50)
.persistence(getApplicationContext().getFilesDir())
.persistence(getApplicationContext().getFilesDir(), new GsonSpeaker())
.using(RxProviders.class);

/* for (int i = 0; i < 1000; i++) {
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ buildscript {
allprojects {
repositories {
jcenter()
maven { url 'https://jitpack.io' }
}
}

Expand Down
8 changes: 5 additions & 3 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ artifacts {
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])

apt "com.google.dagger:dagger-compiler:2.4"
compile "com.google.dagger:dagger:2.4"
compile "org.glassfish:javax.annotation:10.0-b28"

compile "io.reactivex:rxjava:1.1.5"
compile 'com.google.code.gson:gson:2.5'
compile 'com.github.VictorAlbertos.Jolyglot:api:0.0.1'

testCompile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.1'
testCompile 'com.github.VictorAlbertos.Jolyglot:jackson:0.0.1'
testCompile 'com.github.VictorAlbertos.Jolyglot:moshi:0.0.1'

testCompile "junit:junit:4.12"
}
117 changes: 27 additions & 90 deletions core/src/main/java/io/rx_cache/internal/Disk.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

package io.rx_cache.internal;

import com.google.gson.Gson;
import com.google.gson.internal.$Gson$Types;

import java.io.BufferedReader;
import java.io.File;
Expand All @@ -34,17 +32,20 @@
import javax.inject.Inject;

import io.rx_cache.internal.encrypt.FileEncryptor;
import io.victoralbertos.jolyglot.Jolyglot;

/**
* Save objects in disk and evict them too. It uses Gson as json parser.
*/
public final class Disk implements Persistence {
private final File cacheDirectory;
private final FileEncryptor fileEncryptor;
private final Jolyglot jolyglot;

@Inject public Disk(File cacheDirectory, FileEncryptor fileEncryptor) {
@Inject public Disk(File cacheDirectory, FileEncryptor fileEncryptor, Jolyglot jolyglot) {
this.cacheDirectory = cacheDirectory;
this.fileEncryptor = fileEncryptor;
this.jolyglot = jolyglot;
}

/** Save in disk the Record passed.
Expand Down Expand Up @@ -100,7 +101,7 @@ public final class Disk implements Persistence {
* @param encryptKey The key used to encrypt/decrypt the record to be persisted. See {@link io.rx_cache.EncryptKey}
* */
public void save(String key, Object data, boolean isEncrypted, String encryptKey) {
String wrapperJSONSerialized = new Gson().toJson(data);
String wrapperJSONSerialized = jolyglot.toJson(data);
FileWriter fileWriter = null;

try {
Expand All @@ -115,7 +116,7 @@ public void save(String key, Object data, boolean isEncrypted, String encryptKey
fileEncryptor.encrypt(encryptKey, new File(cacheDirectory, key));

} catch (Exception e) {
throw new RuntimeException(e.getMessage());
throw new RuntimeException(e);
} finally {
try {
if (fileWriter != null) {
Expand Down Expand Up @@ -152,32 +153,18 @@ public void save(String key, Object data, boolean isEncrypted, String encryptKey
* */
public <T> T retrieve(String key, final Class<T> clazz, boolean isEncrypted, String encryptKey) {
File file = new File(cacheDirectory, key);
BufferedReader bufferedReader = null;

if (isEncrypted)
file = fileEncryptor.decrypt(encryptKey, file);

try {
bufferedReader = new BufferedReader(new FileReader(file.getAbsoluteFile()));
T data = new Gson().fromJson(bufferedReader, clazz);

if (isEncrypted)
file.delete();

T data = jolyglot.fromJson(file, clazz);
return data;
} catch (Exception ignore) {
return null;
} finally {
if (isEncrypted)
file.delete();

try {
if (bufferedReader != null) {
bufferedReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

Expand All @@ -187,19 +174,18 @@ public <T> T retrieve(String key, final Class<T> clazz, boolean isEncrypted, Str
* @param encryptKey The key used to encrypt/decrypt the record to be persisted. See {@link io.rx_cache.EncryptKey}
* */
@Override public <T> Record<T> retrieveRecord(String key, boolean isEncrypted, String encryptKey) {
BufferedReader readerTempRecord = null;
BufferedReader reader = null;
File file = new File(cacheDirectory, key);

try {
if (isEncrypted)
file = fileEncryptor.decrypt(encryptKey, file);

readerTempRecord = new BufferedReader(new FileReader(file.getAbsoluteFile()));
Record tempDiskRecord = new Gson().fromJson(readerTempRecord, Record.class);
readerTempRecord.close();
/* Scanner scanner = new Scanner(file);
String text = scanner.useDelimiter("\\A").next();
scanner.close();*/

Record tempDiskRecord = jolyglot.fromJson(file, Record.class);

reader = new BufferedReader(new FileReader(file.getAbsoluteFile()));
Class classData = Class.forName(tempDiskRecord.getDataClassName());
Class classCollectionData = tempDiskRecord.getDataCollectionClassName() == null
? Object.class : Class.forName(tempDiskRecord.getDataCollectionClassName());
Expand All @@ -210,20 +196,20 @@ public <T> T retrieve(String key, final Class<T> clazz, boolean isEncrypted, Str
Record<T> diskRecord;

if (isCollection) {
Type typeCollection = $Gson$Types.newParameterizedTypeWithOwner(null, classCollectionData, classData);
Type typeRecord = $Gson$Types.newParameterizedTypeWithOwner(null, Record.class, typeCollection, classData);
diskRecord = new Gson().fromJson(reader, typeRecord);
Type typeCollection = jolyglot.newParameterizedType(classCollectionData, classData);
Type typeRecord = jolyglot.newParameterizedType(Record.class, typeCollection);
diskRecord = jolyglot.fromJson(file.getAbsoluteFile(), typeRecord);
} else if (isArray) {
Type typeRecord = $Gson$Types.newParameterizedTypeWithOwner(null, Record.class, classCollectionData);
diskRecord = new Gson().fromJson(reader, typeRecord);
Type typeRecord = jolyglot.newParameterizedType(Record.class, classCollectionData);
diskRecord = jolyglot.fromJson(file.getAbsoluteFile(), typeRecord);
} else if (isMap) {
Class classKeyMap = Class.forName(tempDiskRecord.getDataKeyMapClassName());
Type typeMap = $Gson$Types.newParameterizedTypeWithOwner(null, classCollectionData, classKeyMap, classData);
Type typeRecord = $Gson$Types.newParameterizedTypeWithOwner(null, Record.class, typeMap, classData);
diskRecord = new Gson().fromJson(reader, typeRecord);
Type typeMap = jolyglot.newParameterizedType(classCollectionData, classKeyMap, classData);
Type typeRecord = jolyglot.newParameterizedType(Record.class, typeMap);
diskRecord = jolyglot.fromJson(file.getAbsoluteFile(), typeRecord);
} else {
Type type = $Gson$Types.newParameterizedTypeWithOwner(null, Record.class, classData);
diskRecord = new Gson().fromJson(reader, type);
Type type = jolyglot.newParameterizedType(Record.class, classData);
diskRecord = jolyglot.fromJson(file.getAbsoluteFile(), type);
}

diskRecord.setSizeOnMb(file.length()/1024f/1024f);
Expand All @@ -232,17 +218,6 @@ public <T> T retrieve(String key, final Class<T> clazz, boolean isEncrypted, Str
} catch (Exception ignore) {
return null;
} finally {
try {
if (readerTempRecord != null) {
readerTempRecord.close();
}
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}

if (isEncrypted)
file.delete();
}
Expand Down Expand Up @@ -280,27 +255,13 @@ private String getFileContent(File file) {
* @param classData type class contained by the collection, not the collection itself
* */
public <C extends Collection<T>, T> C retrieveCollection(String key, Class<C> classCollection, Class<T> classData) {
BufferedReader reader = null;

try {
File file = new File(cacheDirectory, key);
reader = new BufferedReader(new FileReader(file.getAbsoluteFile()));

Type typeCollection = $Gson$Types.newParameterizedTypeWithOwner(null, classCollection, classData);
T data = new Gson().fromJson(reader, typeCollection);

Type typeCollection = jolyglot.newParameterizedType(classCollection, classData);
T data = jolyglot.fromJson(file, typeCollection);
return (C) data;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

Expand All @@ -311,27 +272,15 @@ public <C extends Collection<T>, T> C retrieveCollection(String key, Class<C> cl
* @param classMapValue type class of the Map value
* */
public <M extends Map<K,V>, K, V> M retrieveMap(String key, Class classMap, Class<K> classMapKey, Class<V> classMapValue) {
BufferedReader reader = null;

try {
File file = new File(cacheDirectory, key);
reader = new BufferedReader(new FileReader(file.getAbsoluteFile()));

Type typeMap = $Gson$Types.newParameterizedTypeWithOwner(null, classMap, classMapKey, classMapValue);
Object data = new Gson().fromJson(reader, typeMap);
Type typeMap = jolyglot.newParameterizedType(classMap, classMapKey, classMapValue);
Object data = jolyglot.fromJson(file, typeMap);

return (M) data;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

Expand All @@ -340,27 +289,15 @@ public <M extends Map<K,V>, K, V> M retrieveMap(String key, Class classMap, Clas
* @param classData type class contained by the Array
* */
public <T> T[] retrieveArray(String key, Class<T> classData) {
BufferedReader reader = null;

try {
File file = new File(cacheDirectory, key);
reader = new BufferedReader(new FileReader(file.getAbsoluteFile()));

Class<?> clazzArray = Array.newInstance(classData, 1).getClass();
Object data = new Gson().fromJson(reader, clazzArray);
Object data = jolyglot.fromJson(file, clazzArray);

return (T[]) data;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/io/rx_cache/internal/Locale.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public interface Locale {
String INVALID_RETURN_TYPE = " needs to return an Observable<T> or Observable<Reply<T>>" ;
String NOT_DATA_RETURN_WHEN_CALLING_OBSERVABLE_LOADER = "The Loader provided did not return any data and there is not data to load from the Cache";
String REPOSITORY_DISK_ADAPTER_CAN_NOT_BE_NULL = "File cache directory can not be null";
String PERSISTENCE_CAN_NOT_BE_NULL = "Persistence can not be null";
String JSON_CONVERTER_CAN_NOT_BE_NULL = "JsonConverter can not be null";
String NOT_OBSERVABLE_LOADER_FOUND = " requires an instance of type observable";
String JUST_ONE_INSTANCE = " requires just one instance of type ";
String EVICT_DYNAMIC_KEY_PROVIDED_BUT_NOT_PROVIDED_ANY_DYNAMIC_KEY = " EvictDynamicKey was provided but not was provided any DynamicKey";
Expand Down
Loading