package org.moca.util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.moca.db.MocaDB.PatientSQLFormat;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
/**
* Contains logic to load the word of words and definitions and find a list of matching words
* given a query. Everything is held in memory; this is not a robust way to serve lots of
* words and is only for demo purposes.
*
* You may want to consider using an SQLite database. In practice, you'll want to make sure your
* suggestion provider is as efficient as possible, as the system will be taxed while performing
* searches across many sources for each keystroke the user enters into Quick Search Box.
*/
public class SearchHelper {
public static class Patient {
public final String firstName;
public final String lastName;
public final String id;
public Patient(String firstName, String lastName, String id) {
this.firstName = firstName;
this.lastName = lastName;
this.id = id;
}
public String getPatientId() {
return id;
}
public String toString() {
return lastName + ", " + firstName;
}
}
private static final String[] PROJECTION = new String[] {
PatientSQLFormat._ID,
PatientSQLFormat.PATIENT_ID,
PatientSQLFormat.PATIENT_LASTNAME,
PatientSQLFormat.PATIENT_FIRSTNAME
};
private static final String TAG = SearchHelper.class.toString();
private static final SearchHelper sInstance = new SearchHelper();
public static SearchHelper getInstance() {
return sInstance;
}
private final Map<String, List<Patient>> mDict = new ConcurrentHashMap<String, List<Patient>>();
private SearchHelper() {
}
private boolean mLoaded = false;
/**
* Loads the words and definitions if they haven't been loaded already.
*
* @param resources Used to load the file containing the words and definitions.
*/
public synchronized void ensureLoaded(final Resources resources, final Context c) {
if (mLoaded) return;
new Thread(new Runnable() {
public void run() {
try {
Log.i(TAG, "about to load patients");
loadPatients(resources, c);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
}
private synchronized void loadPatients(Resources resources, Context c) throws IOException {
if (mLoaded) return;
Log.i(TAG, "Loading patients");
Uri uri = PatientSQLFormat.CONTENT_URI;
Cursor cursor = c.getContentResolver().query(uri, PROJECTION, null,
null, PatientSQLFormat.DEFAULT_SORT_ORDER);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
String fName = cursor.getString(1);
String lName = cursor.getString(2);
String id = cursor.getString(3);
addPatient(fName, lName, id);
cursor.moveToNext();
}
cursor.close();
Log.i(TAG, "Cursor in loadPatients has been closed");
mLoaded = true;
}
@SuppressWarnings("unchecked")
public List<Patient> getMatches(String query) {
List<Patient> list = mDict.get(query);
Log.i(TAG, "getMatches has been called with query: " + query
+ "and is returning: " + (list == null ? Collections.EMPTY_LIST : list));
return list == null ? Collections.EMPTY_LIST : list;
}
private void addPatient(String firstName, String lastName, String id) {
final Patient thePatient = new Patient(firstName, lastName, id);
final int len1 = lastName.length();
for (int i = 0; i < len1; i++) {
String prefix = lastName.substring(0, len1 - i);
addMatch(prefix, thePatient);
}
final int len2 = firstName.length();
for (int i = 0; i < len2; i++) {
String prefix = firstName.substring(0, len2 - i);
addMatch(prefix, thePatient);
}
final int len3 = id.length();
for (int i = 0; i < len3; i++) {
String prefix = id.substring(0, len3 - i);
addMatch(prefix, thePatient);
}
}
private void addMatch(String query, Patient patient) {
Log.i(TAG, "Adding match with query = " + query + ", patient = " + patient);
List<Patient> matches = mDict.get(query);
if (matches == null) {
matches = new ArrayList<Patient>();
mDict.put(query, matches);
}
matches.add(patient);
}
}
|