- Added new methods that allow a query of a single term over name, address, phone, telegram an website fields

- Linking this result to the code that handles the UI update (working for merchants only)
This commit is contained in:
Nelson R. Perez 2019-01-28 18:34:07 -05:00
parent 07e39e9001
commit aebff15033
8 changed files with 144 additions and 21 deletions

View file

@ -47,6 +47,11 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// Gradle automatically adds 'android.test.runner' as a dependency.
useLibrary 'android.test.runner'
useLibrary 'android.test.base'
useLibrary 'android.test.mock'
}
dependencies {
@ -100,9 +105,12 @@ dependencies {
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
// TODO enable and make proper testing
// testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.12'
// Core library
androidTestImplementation 'androidx.test:core:1.1.0'
// testImplementation "androidx.arch.core:core-testing:$lifecycle_version"
// testImplementation "androidx.room:room-testing:$room_version"
// androidTestImplementation 'androidx.test:runner:1.1.0'
// androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}

View file

@ -0,0 +1,65 @@
package cy.agorise.bitsybitshareswallet;
import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.runner.AndroidJUnit4
import cy.agorise.bitsybitshareswallet.database.BitsyDatabase
import cy.agorise.bitsybitshareswallet.database.entities.Merchant
import org.junit.After
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.io.IOException
@RunWith(AndroidJUnit4::class)
public class MerchantQueryTest {
private lateinit var db: BitsyDatabase
@Before
fun createDb(){
val context = ApplicationProvider.getApplicationContext<Context>()
db = Room.inMemoryDatabaseBuilder(context, BitsyDatabase::class.java).build()
// Creating a few sample merchants
val merchant1 = Merchant("5c23c8c234c83f0013e67786",
"Café del Mar",
"Address1",
17.82834,
-9.38483,
"+1 999.999.9999",
"@user",
"https://100Natural.com")
val merchant2 = Merchant("5c23c91a34c83f0013e67787",
"Condesa Acapulco",
"Address2",
13.82834,
-67.38483,
"+1 999.999.9999",
"@user",
"https://100Natural.com")
db.merchantDao().insert(merchant1)
db.merchantDao().insert(merchant2)
}
@After
@Throws(IOException::class)
fun closeDb(){
db.close()
}
@Test
fun testSimpleQuery(){
val allMerchants = db.merchantDao().getAllSync()
Assert.assertEquals(2, allMerchants.size)
}
@Test
fun testSearchQuery(){
val query = "%con%"
val merchants = db.merchantDao().findMerchantsByWordSync(query)
Assert.assertEquals(1, merchants.size)
Assert.assertEquals(merchants[0].name, "Condesa Acapulco")
}
}

View file

@ -6,6 +6,7 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import cy.agorise.bitsybitshareswallet.database.entities.Merchant
import io.reactivex.Single
@Dao
interface MerchantDao {
@ -18,6 +19,15 @@ interface MerchantDao {
@Query("SELECT * FROM merchants")
fun getAll(): LiveData<List<Merchant>>
@Query("SELECT * FROM merchants")
fun getAllSync(): List<Merchant>
@Query("SELECT * FROM merchants WHERE (name LIKE :query) OR (address LIKE :query) OR (phone LIKE :query) OR (telegram LIKE :query) OR (website LIKE :query)")
fun findMerchantsByWord(query: String): Single<List<Merchant>>
@Query("SELECT * FROM merchants WHERE (name LIKE :query) OR (address LIKE :query) OR (phone LIKE :query) OR (telegram LIKE :query) OR (website LIKE :query)")
fun findMerchantsByWordSync(query: String): List<Merchant>
@Query("DELETE FROM merchants")
fun deleteAll()
}

View file

@ -6,6 +6,7 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import cy.agorise.bitsybitshareswallet.database.entities.Teller
import io.reactivex.Single
@Dao
interface TellerDao {
@ -18,6 +19,9 @@ interface TellerDao {
@Query("SELECT * FROM tellers")
fun getAll(): LiveData<List<Teller>>
@Query("SELECT * FROM tellers WHERE (name LIKE :query) OR (address LIKE :query) OR (phone LIKE :query) OR (telegram LIKE :query) OR (website LIKE :query)")
fun findTellersByWord(query: String): Single<List<Teller>>
@Query("DELETE FROM tellers")
fun deleteAll()
}

View file

@ -6,13 +6,8 @@ import android.content.pm.PackageManager
import android.database.Cursor
import android.database.MatrixCursor
import android.os.Bundle
import android.util.Log
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import cy.agorise.bitsybitshareswallet.R
import android.preference.PreferenceManager
import android.util.Log
import android.view.*
import android.widget.PopupWindow
import android.widget.TextView
@ -27,12 +22,18 @@ import androidx.lifecycle.ViewModelProviders
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.model.*
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.SupportMapFragment
import com.google.android.gms.maps.model.LatLngBounds
import com.google.android.gms.maps.model.MapStyleOptions
import com.google.android.gms.maps.model.Marker
import com.google.maps.android.MarkerManager
import com.google.maps.android.clustering.Cluster
import com.google.maps.android.clustering.ClusterItem
import com.google.maps.android.clustering.ClusterManager
import com.jakewharton.rxbinding3.appcompat.queryTextChangeEvents
import cy.agorise.bitsybitshareswallet.R
import cy.agorise.bitsybitshareswallet.database.entities.Merchant
import cy.agorise.bitsybitshareswallet.database.entities.Teller
import cy.agorise.bitsybitshareswallet.utils.Constants
@ -42,7 +43,9 @@ import cy.agorise.bitsybitshareswallet.utils.toast
import cy.agorise.bitsybitshareswallet.viewmodels.MerchantViewModel
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import java.lang.Exception
import io.reactivex.schedulers.Schedulers
import java.math.BigInteger
import java.util.*
import java.util.concurrent.TimeUnit
@ -173,20 +176,34 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, SearchView.OnSuggestio
}
private fun updateSearchViewSuggestions(query: String) {
// TODO make call to the db to obtain the list of merchants/tellers
val merchObs = mMerchantViewModel.queryMerchants(query)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
// Create a cursor out of an Array
val cursor = MatrixCursor(arrayOf(SUGGEST_COLUMN_ID, SUGGEST_COLUMN_NAME,
SUGGEST_COLUMN_ADDRESS, SUGGEST_COLUMN_IS_MERCHANT, SUGGEST_COLUMN_IMAGE_RESOURCE))
val tellerObs = mMerchantViewModel.queryTellers(query)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
for (i in 1..3) {
if (i%2 == 1)
cursor.addRow(arrayOf(i.toString(), "Merchant $i", "Address $i", 1, R.drawable.ic_merchant_pin))
else
cursor.addRow(arrayOf(i.toString(), "Teller $i", "Address $i", 0, R.drawable.ic_teller_pin))
}
//TODO: Combine the results of both the merchants and teller queries
// val combined: Observable<List<Any>> = Observable.combineLatest<List<Merchant>, List<Teller>, List<Any>>(merchObs, tellerObs, BiFunction { t1: List<Merchant>, t2:List<Teller> -> Arrays.asList(t1, t2)})
merchObs.subscribe({list ->
run {
Log.d(TAG, "list with ${list.size} elements")
val cursor = MatrixCursor(
arrayOf(
SUGGEST_COLUMN_ID, SUGGEST_COLUMN_NAME,
SUGGEST_COLUMN_ADDRESS, SUGGEST_COLUMN_IS_MERCHANT, SUGGEST_COLUMN_IMAGE_RESOURCE
)
)
for (item in list) {
cursor.addRow(arrayOf(BigInteger(item._id, 16).toLong(), item.name, item.address, 1, R.drawable.ic_merchant_pin))
}
mSearchView?.suggestionsAdapter?.changeCursor(cursor)
}
},
{error -> Log.e(TAG, "Error while retrieving autocomplete suggestions. Msg: ${error}")})
mSearchView?.suggestionsAdapter?.changeCursor(cursor)
}
override fun onSuggestionSelect(position: Int): Boolean {

View file

@ -11,6 +11,7 @@ import cy.agorise.bitsybitshareswallet.database.entities.Merchant
import cy.agorise.bitsybitshareswallet.network.FeathersResponse
import cy.agorise.bitsybitshareswallet.network.MerchantsWebservice
import cy.agorise.bitsybitshareswallet.utils.Constants
import io.reactivex.Single
import retrofit2.Call
import retrofit2.Response
import retrofit2.Retrofit
@ -79,4 +80,8 @@ class MerchantRepository internal constructor(val context: Context) : retrofit2.
return null
}
}
fun findMerchantsByWord(query: String): Single<List<Merchant>> {
return mMerchantDao.findMerchantsByWord("%$query%")
}
}

View file

@ -11,6 +11,7 @@ import cy.agorise.bitsybitshareswallet.database.entities.Teller
import cy.agorise.bitsybitshareswallet.network.FeathersResponse
import cy.agorise.bitsybitshareswallet.network.MerchantsWebservice
import cy.agorise.bitsybitshareswallet.utils.Constants
import io.reactivex.Single
import retrofit2.Call
import retrofit2.Response
import retrofit2.Retrofit
@ -79,4 +80,8 @@ class TellerRepository internal constructor(val context: Context) : retrofit2.Ca
return null
}
}
fun findTellerByWord(word: String): Single<List<Teller>> {
return mTellerDao.findTellersByWord("%$word%")
}
}

View file

@ -7,6 +7,7 @@ import cy.agorise.bitsybitshareswallet.database.entities.Merchant
import cy.agorise.bitsybitshareswallet.database.entities.Teller
import cy.agorise.bitsybitshareswallet.repositories.MerchantRepository
import cy.agorise.bitsybitshareswallet.repositories.TellerRepository
import io.reactivex.Single
class MerchantViewModel(application: Application) : AndroidViewModel(application) {
private var mMerchantRepository = MerchantRepository(application)
@ -19,4 +20,12 @@ class MerchantViewModel(application: Application) : AndroidViewModel(application
internal fun getAllTellers(): LiveData<List<Teller>> {
return mTellerRepository.getAll()
}
fun queryMerchants(query: String): Single<List<Merchant>> {
return mMerchantRepository.findMerchantsByWord(query)
}
fun queryTellers(query: String): Single<List<Teller>> {
return mTellerRepository.findTellerByWord(query)
}
}