diff --git a/store2store/src/androidTest/java/com/playmoweb/store2store/mock/MemoryDao.java b/store2store/src/androidTest/java/com/playmoweb/store2store/mock/MemoryDao.java index b0277cc..9ebd4f0 100644 --- a/store2store/src/androidTest/java/com/playmoweb/store2store/mock/MemoryDao.java +++ b/store2store/src/androidTest/java/com/playmoweb/store2store/mock/MemoryDao.java @@ -6,6 +6,7 @@ import com.playmoweb.store2store.utils.SortType; import com.playmoweb.store2store.utils.SortingMode; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.List; @@ -45,8 +46,17 @@ public Flowable>> getAll(final List items) { @Override public Flowable> getOne(Filter filter, SortingMode sortingMode) { - if(sortingMode != null && sortingMode.sort == SortType.DESCENDING){ - return Flowable.just(Optional.wrap(models.get(models.size() - 1))); + if(sortingMode != null){ + boolean reverse = false; + for(AbstractMap.SimpleEntry e : sortingMode.entries){ + if(e.getValue() == SortType.DESCENDING){ + reverse = true; + break; + } + } + if(reverse) { + return Flowable.just(Optional.wrap(models.get(models.size() - 1))); + } } return Flowable.just(Optional.wrap(models.get(0))); } diff --git a/store2store/src/androidTest/java/com/playmoweb/store2store/mock/TestStore.java b/store2store/src/androidTest/java/com/playmoweb/store2store/mock/TestStore.java index 9d0d509..a4ec5e4 100644 --- a/store2store/src/androidTest/java/com/playmoweb/store2store/mock/TestStore.java +++ b/store2store/src/androidTest/java/com/playmoweb/store2store/mock/TestStore.java @@ -7,6 +7,7 @@ import com.playmoweb.store2store.utils.SortType; import com.playmoweb.store2store.utils.SortingMode; +import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -44,8 +45,17 @@ public Flowable>> getAll(Filter filter, SortingMode sor list.add(new TestModel(20)); list.add(new TestModel(30)); - if(sortingMode != null && sortingMode.sort == SortType.DESCENDING){ - Collections.reverse(list); + if(sortingMode != null){ + boolean reverse = false; + for(AbstractMap.SimpleEntry e : sortingMode.entries){ + if(e.getValue() == SortType.DESCENDING){ + reverse = true; + break; + } + } + if(reverse) { + Collections.reverse(list); + } } return Flowable.just(Optional.wrap(list)).delay(1, TimeUnit.SECONDS); diff --git a/store2store/src/main/java/com/playmoweb/store2store/store/StoreService.java b/store2store/src/main/java/com/playmoweb/store2store/store/StoreService.java index 53a9055..a1af04f 100644 --- a/store2store/src/main/java/com/playmoweb/store2store/store/StoreService.java +++ b/store2store/src/main/java/com/playmoweb/store2store/store/StoreService.java @@ -12,9 +12,10 @@ /** * Abstract StoreService - * @author Thibaud Giovannetti - * @by Playmoweb - * @date 07/09/2017 + * + * @author Thibaud Giovannetti + * @by Playmoweb + * @date 07/09/2017 */ public abstract class StoreService extends StoreDao { @@ -28,6 +29,14 @@ public abstract class StoreService extends StoreDao { */ private final StoreDao dao; + /** + * If true, this Service will be used as a cache (first call). + * It's a read-only feature (getAll, getById, getOne, ...). + * + * @warning If this service is used as a cache and its access is slow, it will reduce drastically the performances of syncing + */ + private final boolean isCache; + /** * List of store synced with this one */ @@ -42,20 +51,29 @@ public abstract class StoreService extends StoreDao { * Create a typed Store */ public StoreService(Class clazz, StoreDao dao) { + this(clazz, dao, false); + } + + /** + * Create a typed store with cache information + */ + public StoreService(Class clazz, StoreDao dao, boolean isCache) { this.clazz = clazz; this.dao = dao; + this.isCache = isCache; } /** * Add a Store to be synced to */ - public StoreService syncWith(StoreService otherStore){ + public StoreService syncWith(StoreService otherStore) { syncedStore = otherStore; return this; } /** * Get the dao used by this Store + * * @return */ public StoreDao getDao() { @@ -65,30 +83,35 @@ public StoreDao getDao() { /** * Clear all remaining disposables */ - public void clearAllDisposables(){ + public void clearAllDisposables() { compositeDisposable.clear(); } /** * This Store is Synced with another + * * @return */ - public boolean hasSyncedStore(){ + public boolean hasSyncedStore() { return syncedStore != null; } + public boolean isCache() { + return isCache; + } + @Override public Flowable>> getAll(final Filter filter, final SortingMode sortingMode) { List>>> flowables = new ArrayList<>(); Flowable>> flowStorage = dao.getAll(filter, sortingMode); - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = flowStorage .flatMap(new Function>, Flowable>>>() { @Override public Flowable>> apply(Optional> items) throws Exception { final List copy = new ArrayList<>(items.get()); - if(filter == null) { + if (filter == null) { // full replacement, we clean up the Store dao return syncedStore.deleteAll().map(new Function>>() { @Override @@ -107,6 +130,10 @@ public Flowable>> apply(Optional> items) throws Excepti } }); + if (syncedStore.isCache()) { + return flowStorage.startWith(syncedStore.getAll(filter, sortingMode)); + } + flowables.add(syncedStore.getAll(filter, sortingMode)); } @@ -119,7 +146,7 @@ public Flowable>> getAll(final List items) { List>>> flowables = new ArrayList<>(); Flowable>> flowStorage = dao.getAll(items); - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = flowStorage .flatMap(new Function>, Flowable>>>() { @Override @@ -128,6 +155,10 @@ public Flowable>> apply(Optional> items) throws Excepti } }); + if (syncedStore.isCache()) { + return flowStorage.startWith(syncedStore.getAll(items)); + } + flowables.add(syncedStore.getAll(items)); } @@ -148,7 +179,7 @@ public Flowable> getOne(final Filter filter, final SortingMode sorti List>> flowables = new ArrayList<>(); Flowable> flowStorage = dao.getOne(filter, sortingMode); - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = flowStorage .flatMap(new Function, Flowable>>() { @Override @@ -157,6 +188,10 @@ public Flowable> apply(Optional item) throws Exception { } }); + if (syncedStore.isCache()) { + return flowStorage.startWith(syncedStore.getOne(filter, sortingMode)); + } + flowables.add(syncedStore.getOne(filter, sortingMode)); } @@ -169,7 +204,7 @@ public Flowable> getOne(final T item) { List>> flowables = new ArrayList<>(); Flowable> flowStorage = dao.getOne(item); - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = flowStorage .flatMap(new Function, Flowable>>() { @Override @@ -177,7 +212,9 @@ public Flowable> apply(Optional item) throws Exception { return syncedStore.insertOrUpdate(item.get()); } }); - + if (syncedStore.isCache()) { + return flowStorage.startWith(syncedStore.getOne(item)); + } flowables.add(syncedStore.getOne(item)); } @@ -202,7 +239,7 @@ public Flowable> getById(final int id) { List>> flowables = new ArrayList<>(); Flowable> flowStorage = dao.getById(id); - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = flowStorage .flatMap(new Function, Flowable>>() { @Override @@ -210,7 +247,9 @@ public Flowable> apply(final Optional item) throws Exception { return syncedStore.insertOrUpdate(item.get()); } }); - + if (syncedStore.isCache()) { + return flowStorage.startWith(syncedStore.getById(id)); + } flowables.add(syncedStore.getById(id)); } @@ -223,7 +262,7 @@ public Flowable>> insert(final List items) { List>>> flowables = new ArrayList<>(); Flowable>> flowStorage = dao.insert(items); - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = flowStorage .onErrorResumeNext(new Function>>>() { @Override @@ -255,7 +294,7 @@ public Flowable> insert(final T item) { List>> flowables = new ArrayList<>(); Flowable> flowStorage = dao.insert(item); - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = flowStorage .onErrorResumeNext(new Function>>() { @Override @@ -286,47 +325,47 @@ public Flowable> apply(Optional it) throws Exception { public Flowable>> insertOrUpdate(final List items) { Flowable>> flowStorage; - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = syncedStore.getAll(items) // try to get a copy before trying to update/insert .flatMap(new Function>, Flowable>>>() { @Override public Flowable>> apply(final Optional> originalItems) { return Flowable.concat( - syncedStore.insertOrUpdate(items), - dao.insertOrUpdate(items) - .onErrorResumeNext(new Function>>>() { - @Override - public Flowable>> apply(final Throwable throwable) { - if(originalItems.isNull() || originalItems.get().size() == 0){ - return syncedStore.delete(items).flatMap(new Function>>>() { - @Override - public Flowable>> apply(Integer notUsed) { - return Flowable.error(throwable); - } - }); - } else { - return syncedStore.delete(items) - .flatMap(new Function>>>() { - @Override - public Flowable>> apply(Integer deleteCount) throws Exception { - return syncedStore.insertOrUpdate(originalItems.get()); - } - }) - .flatMap(new Function>, Flowable>>>() { + syncedStore.insertOrUpdate(items), + dao.insertOrUpdate(items) + .onErrorResumeNext(new Function>>>() { + @Override + public Flowable>> apply(final Throwable throwable) { + if (originalItems.isNull() || originalItems.get().size() == 0) { + return syncedStore.delete(items).flatMap(new Function>>>() { @Override - public Flowable>> apply(Optional> notUsed) { + public Flowable>> apply(Integer notUsed) { return Flowable.error(throwable); } }); + } else { + return syncedStore.delete(items) + .flatMap(new Function>>>() { + @Override + public Flowable>> apply(Integer deleteCount) throws Exception { + return syncedStore.insertOrUpdate(originalItems.get()); + } + }) + .flatMap(new Function>, Flowable>>>() { + @Override + public Flowable>> apply(Optional> notUsed) { + return Flowable.error(throwable); + } + }); + } + } + }) + .flatMap(new Function>, Flowable>>>() { + @Override + public Flowable>> apply(Optional> itemInsertedOrUpdated) { + return syncedStore.insertOrUpdate(itemInsertedOrUpdated.get()); } - } - }) - .flatMap(new Function>, Flowable>>>() { - @Override - public Flowable>> apply(Optional> itemInsertedOrUpdated) { - return syncedStore.insertOrUpdate(itemInsertedOrUpdated.get()); - } - }) + }) ); } }); @@ -341,7 +380,7 @@ public Flowable>> apply(Optional> itemInsertedOrUpdated public Flowable> insertOrUpdate(final T item) { Flowable> flowStorage; - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = syncedStore.getOne(item) // get a copy before trying to update/insert .flatMap(new Function, Flowable>>() { @Override @@ -353,7 +392,7 @@ public Flowable> apply(final Optional originalItem) throws Except @Override public Flowable> apply(final Throwable throwable) throws Exception { // the item did not exist before - if(originalItem.isNull()){ + if (originalItem.isNull()) { return syncedStore.delete(item).flatMap(new Function>>() { @Override public Flowable> apply(Integer notUsed) throws Exception { @@ -362,18 +401,18 @@ public Flowable> apply(Integer notUsed) throws Exception { }); } else { // it did exists, re-apply previous version return syncedStore.delete(item) - .flatMap(new Function>>() { - @Override - public Flowable> apply(Integer integer) throws Exception { - return syncedStore.insertOrUpdate(originalItem.get()); - } - }) - .flatMap(new Function, Flowable>>() { - @Override - public Flowable> apply(Optional notUsed) throws Exception { - return Flowable.error(throwable); - } - }); + .flatMap(new Function>>() { + @Override + public Flowable> apply(Integer integer) throws Exception { + return syncedStore.insertOrUpdate(originalItem.get()); + } + }) + .flatMap(new Function, Flowable>>() { + @Override + public Flowable> apply(Optional notUsed) throws Exception { + return Flowable.error(throwable); + } + }); } } }) @@ -397,12 +436,12 @@ public Flowable> apply(Optional itemInsertedOrUpdated) throws Exc public Flowable>> update(final List items) { Flowable>> flowStorage; - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = syncedStore.getAll(items) // try to get a copy before trying to update/insert .flatMap(new Function>, Flowable>>>() { @Override public Flowable>> apply(final Optional> originalItems) { - if(originalItems.isNull() || originalItems.get().size() < items.size()){ + if (originalItems.isNull() || originalItems.get().size() < items.size()) { return Flowable.error(new IllegalArgumentException( "One or many items do not exist and can't be updated. Please use insertOrUpdate if this behaviour is not expected !" )); @@ -449,12 +488,12 @@ public Flowable>> apply(Optional> itemsUpdated) { public Flowable> update(final T item) { Flowable> flowStorage; - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = syncedStore.getOne(item) // get a copy before trying to update/insert .flatMap(new Function, Flowable>>() { @Override public Flowable> apply(final Optional originalItem) throws Exception { - if(originalItem.isNull()){ + if (originalItem.isNull()) { return Flowable.error(new IllegalArgumentException( "This item does not exists and can't be updated. Please use insertOrUpdate if this behaviour is not expected !" )); @@ -509,7 +548,7 @@ public Flowable deleteAll() { // if error again => re-insert syncedStore datas (better than nothing) // if not error, insert fresh datas - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = flowStorage .onErrorResumeNext(new Function>() { @Override @@ -542,7 +581,7 @@ public Flowable delete(final List items) { List> flowables = new ArrayList<>(); Flowable flowStorage = dao.delete(items); - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = flowStorage .onErrorResumeNext(new Function>() { @Override @@ -569,7 +608,7 @@ public Flowable delete(final T item) { List> flowables = new ArrayList<>(); Flowable flowStorage = dao.delete(item); - if(hasSyncedStore()) { + if (hasSyncedStore()) { flowStorage = flowStorage .onErrorResumeNext(new Function>() { @Override