/*
* Copyright(c) 2017 lizhaotailang
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.marktony.espresso.data.source.local;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.util.List;
import io.github.marktony.espresso.data.Package;
import io.github.marktony.espresso.data.source.PackagesDataSource;
import io.github.marktony.espresso.realm.RealmHelper;
import io.reactivex.Observable;
import io.realm.Case;
import io.realm.Realm;
import io.realm.RealmResults;
import io.realm.Sort;
/**
* Created by lizhaotailang on 2017/2/25.
* Concrete implementation of a data source as a db.
*/
public class PackagesLocalDataSource implements PackagesDataSource {
@Nullable
private static PackagesLocalDataSource INSTANCE;
// Prevent direct instantiation
private PackagesLocalDataSource() {
}
// Access this instance for other classes.
public static PackagesLocalDataSource getInstance() {
if (INSTANCE == null) {
INSTANCE = new PackagesLocalDataSource();
}
return INSTANCE;
}
// Destroy the instance.
public static void destroyInstance() {
INSTANCE = null;
}
/**
* Get the packages in database and sort them in timestamp descending.
* @return The observable packages from database.
*/
@Override
public Observable<List<Package>> getPackages() {
Realm rlm = RealmHelper.newRealmInstance();
return Observable.just(rlm.copyFromRealm(rlm.where(Package.class)
.findAllSorted("timestamp", Sort.DESCENDING)));
}
/**
* Get a package in database of specific number.
* @param packNumber The primary key
* or in another words, the package id.
* See {@link Package#number}
* @return The observable package from database.
*/
@Override
public Observable<Package> getPackage(@NonNull String packNumber) {
Realm rlm = RealmHelper.newRealmInstance();
return Observable.just(rlm.copyFromRealm(rlm.where(Package.class)
.equalTo("number", packNumber)
.findFirst()));
}
/**
* Save a package to database.
* @param pack The package to save. See {@link Package}
*/
@Override
public void savePackage(@NonNull Package pack) {
Realm rlm = RealmHelper.newRealmInstance();
// DO NOT forget begin and commit the transaction.
rlm.beginTransaction();
rlm.copyToRealmOrUpdate(pack);
rlm.commitTransaction();
rlm.close();
}
/**
* Delete a package with specific id from database.
* @param packageId The primary key of a package
* or in another words, the package id.
* See {@link Package#number}
*/
@Override
public void deletePackage(@NonNull String packageId) {
Realm rlm = RealmHelper.newRealmInstance();
Package p = rlm.where(Package.class)
.equalTo("number", packageId)
.findFirst();
if (p != null) {
rlm.beginTransaction();
p.deleteFromRealm();
rlm.commitTransaction();
}
rlm.close();
}
@Override
public Observable<List<Package>> refreshPackages() {
// Not required because the {@link PackagesRepository} handles the logic
// of refreshing the packages from all available data source
return null;
}
@Override
public Observable<Package> refreshPackage(@NonNull String packageId) {
// Not required because the {@link PackagesRepository} handles the logic
// of refreshing the packages from all available data source
return null;
}
/**
* Set all the packages which are the unread new read.
*/
@Override
public void setAllPackagesRead() {
Realm rlm = RealmHelper.newRealmInstance();
List<Package> results = rlm.copyFromRealm(rlm.where(Package.class).findAll());
for (Package p : results) {
p.setReadable(false);
p.setPushable(false);
rlm.beginTransaction();
rlm.copyToRealmOrUpdate(p);
rlm.commitTransaction();
}
rlm.close();
}
/**
* Set a package of specific number read or unread new.
* @param packageId The primary key or the package id.
* See {@link Package#number}
* @param readable Read or unread new.
* See {@link Package#readable}
*/
@Override
public void setPackageReadable(@NonNull String packageId, boolean readable) {
Realm rlm = RealmHelper.newRealmInstance();
Package p = rlm.copyFromRealm(rlm.where(Package.class)
.equalTo("number", packageId)
.findFirst());
if (p != null) {
rlm.beginTransaction();
p.setReadable(readable);
// When a package is not readable, it is not pushable.
p.setPushable(readable);
rlm.copyToRealmOrUpdate(p);
rlm.commitTransaction();
rlm.close();
}
}
/**
* Query the existence of a specific number.
* @param packageId the package number to query.
* See {@link Package#number}
* @return whether the number is in the database.
*/
@Override
public boolean isPackageExist(@NonNull String packageId) {
Realm rlm = RealmHelper.newRealmInstance();
RealmResults<Package> results = rlm.where(Package.class)
.equalTo("number", packageId)
.findAll();
return (results != null) && (!results.isEmpty());
}
@Override
public void updatePackageName(@NonNull String packageId, @NonNull String name) {
Realm rlm = RealmHelper.newRealmInstance();
Package p = rlm.where(Package.class)
.equalTo("number", packageId)
.findFirst();
if (p != null) {
rlm.beginTransaction();
p.setName(name);
rlm.copyToRealmOrUpdate(p);
rlm.commitTransaction();
}
rlm.close();
}
@Override
public Observable<List<Package>> searchPackages(@NonNull String keyWords) {
Realm rlm = RealmHelper.newRealmInstance();
return Observable.fromIterable(rlm.copyFromRealm(
rlm.where(Package.class)
.like("name", "*" + keyWords + "*", Case.INSENSITIVE)
.or()
.like("companyChineseName", "*" + keyWords + "*", Case.INSENSITIVE)
.or()
.like("company", "*" + keyWords + "*", Case.INSENSITIVE)
.or()
.like("number", "*" + keyWords + "*", Case.INSENSITIVE)
.findAll()))
.toList()
.toObservable();
}
}