package edu.vanderbilt.vm.guide.ui.adapter; import java.util.ArrayList; import edu.vanderbilt.vm.guide.util.Geomancer; import edu.vanderbilt.vm.guide.util.GuideConstants.PlaceCategories; import android.content.Context; import android.database.Cursor; import android.location.Location; public class CursorIndexerFactory { public interface CursorIndexer { boolean isHeader(int position); int getDBRow(int position); String getHeaderTitle(int position); int categoriesCount(); } public static CursorIndexer getAlphabeticalIndexer(Context ctx, Cursor cursor, int nameColIx) { return new AlphabeticalIndexer(ctx, cursor, nameColIx); } public static CursorIndexer getDistanceIndexer(Context ctx, Cursor cursor, int latColIx, int lngColIx) { return new DistanceIndexer(ctx, cursor, latColIx, lngColIx); } public static CursorIndexer getCategoricalIndexer(Context ctx, Cursor cursor, int catColIx) { return new CategoricalIndexer(ctx, cursor, catColIx); } // ========== END public interface ========== // private static class AlphabeticalIndexer implements CursorIndexer { private ArrayList<Integer> mEnigma; private ArrayList<HeaderRecord> mRecords; private int mCategories = 26; private static class HeaderRecord { final String mTitle; final ArrayList<Integer> mChild; public HeaderRecord(String s) { mTitle = s; mChild = new ArrayList<Integer>(); } } public AlphabeticalIndexer(Context ctx, Cursor cursor, int nameColIx) { // initialize records mRecords = new ArrayList<HeaderRecord>(); char c = 'A'; for (int i = 0; i < mCategories; i++) { mRecords.add(new HeaderRecord(String.valueOf(c))); c++; } HeaderRecord rec = new HeaderRecord("0-9"); mRecords.add(rec); // iterates through the database and make an index if (cursor.moveToFirst()) { String initial; boolean isChar; do { initial = cursor.getString(nameColIx).substring(0, 1); isChar = false; for (int i = 0; i < mRecords.size() - 1; i++) { if (initial.equalsIgnoreCase(mRecords.get(i).mTitle)) { mRecords.get(i).mChild.add(cursor.getPosition()); isChar = true; break; } } if (!isChar) { // add to final category mRecords.get(mRecords.size() - 1).mChild.add(cursor.getPosition()); } } while (cursor.moveToNext()); } // Build HashMap based of the information stored in mRecord int listPosition = 0; mEnigma = new ArrayList<Integer>(); for (int i = 0; i < mRecords.size(); i++) { if (mRecords.get(i).mChild.size() == 0) { mCategories--; } else { mEnigma.add(listPosition, -(i + 1)); listPosition++; for (Integer child : mRecords.get(i).mChild) { mEnigma.add(listPosition, child); listPosition++; } } } } @Override public boolean isHeader(int position) { return mEnigma.get(position) < 0; } @Override public int getDBRow(int position) { int row = mEnigma.get(position); if (row > -1) { return row; } else { return 0; // this is a workaround. For some reason the listView // is trying to get the id of the header. } } @Override public String getHeaderTitle(int position) { if (isHeader(position)) { return mRecords.get(-(mEnigma.get(position)) - 1).mTitle; } else { throw new IllegalStateException("Is not a header."); } } @Override public int categoriesCount() { return mCategories; } } private static class DistanceIndexer implements CursorIndexer { private ArrayList<Integer> mEnigma; private ArrayList<HeaderRecord> mRecords; private int mCategories = 26; private static class HeaderRecord { final double mDist; // in meters final String mTitle; final ArrayList<Integer> mChild; public HeaderRecord(String s, double d) { mTitle = s; mDist = d; mChild = new ArrayList<Integer>(); } } public DistanceIndexer(Context ctx, Cursor cursor, int latColIx, int lngColIx) { // Initializing the Header records mRecords = new ArrayList<HeaderRecord>(); mRecords.add(new HeaderRecord("100 ft", 30.5)); mRecords.add(new HeaderRecord("200 ft", 61)); mRecords.add(new HeaderRecord("400 ft", 122)); mRecords.add(new HeaderRecord("800 ft", 244)); mRecords.add(new HeaderRecord("1000 ft", 304.8)); mRecords.add(new HeaderRecord("0.3 mi", 483)); mRecords.add(new HeaderRecord("0.6 mi", 965.6)); mRecords.add(new HeaderRecord("1.2 mi", 1931)); mRecords.add(new HeaderRecord("2.4 mi", 3862)); mRecords.add(new HeaderRecord("In a galaxy far far away", 10000000)); mCategories = mRecords.size(); // Scanning the database to index if (cursor.moveToFirst()) { Location current = Geomancer.getDeviceLocation(); Location tmp = new Location("Temp"); do { tmp.setLatitude(Double.parseDouble(cursor.getString(latColIx))); tmp.setLongitude(Double.parseDouble(cursor.getString(lngColIx))); for (int i = 0; i < mRecords.size();i++) { if (current.distanceTo(tmp) < mRecords.get(i).mDist) { mRecords.get(i).mChild.add(cursor.getPosition()); break; } } } while (cursor.moveToNext()); } // Build HashMap based of the information stored in mRecord int listPosition = 0; mEnigma = new ArrayList<Integer>(); for (int i = 0; i < mRecords.size(); i++) { if (mRecords.get(i).mChild.size() == 0) { mCategories--; } else { mEnigma.add(listPosition, -(i + 1)); listPosition++; for (Integer child : mRecords.get(i).mChild) { mEnigma.add(listPosition, child); listPosition++; } } } } @Override public boolean isHeader(int position) { return mEnigma.get(position) < 0; } @Override public int getDBRow(int position) { return mEnigma.get(position); } @Override public String getHeaderTitle(int position) { if (isHeader(position)) { return mRecords.get(-(mEnigma.get(position)) - 1).mTitle; } else { throw new IllegalStateException("Is not a header."); } } @Override public int categoriesCount() { return mCategories; } } private static class CategoricalIndexer implements CursorIndexer { private ArrayList<Integer> mEnigma; private ArrayList<HeaderRecord> mRecords; private int mCategories; private static class HeaderRecord { final String mTitle; final PlaceCategories mCat; final ArrayList<Integer> mChild; public HeaderRecord(PlaceCategories d) { mCat = d; mTitle = d.text(); mChild = new ArrayList<Integer>(); } } public CategoricalIndexer(Context ctx, Cursor cursor, int catColIx) { // Initializing the Header records mRecords = new ArrayList<HeaderRecord>(); for (PlaceCategories c : PlaceCategories.values()) { mRecords.add(new HeaderRecord(c)); } mCategories = mRecords.size(); // iterates through the database and make an index if (cursor.moveToFirst()) { String catStr; boolean isCat; do { catStr = cursor.getString(catColIx); isCat = false; //logger.info("Category String from database: " + catStr); for (int i = 0; i < mRecords.size() - 1; i++) { if (catStr.equalsIgnoreCase(mRecords.get(i).mCat.text())) { mRecords.get(i).mChild.add(cursor.getPosition()); isCat = true; break; } } if (!isCat) { // add to final category mRecords.get(mRecords.size() - 1).mChild.add(cursor.getPosition()); } } while (cursor.moveToNext()); } // Build HashMap based of the information stored in mRecord int listPosition = 0; mEnigma = new ArrayList<Integer>(); for (int i = 0; i < mRecords.size(); i++) { if (mRecords.get(i).mChild.size() == 0) { //logger.info("Size of Records' child: " + mRecord.get(i).mChild.size()); mCategories--; } else { mEnigma.add(listPosition, -(i + 1)); listPosition++; for (Integer child : mRecords.get(i).mChild) { mEnigma.add(listPosition, child); listPosition++; } } } } @Override public boolean isHeader(int position) { return mEnigma.get(position) < 0; } @Override public int getDBRow(int position) { return mEnigma.get(position); } @Override public String getHeaderTitle(int position) { if (isHeader(position)) { return mRecords.get(-(mEnigma.get(position)) - 1).mTitle; } else { throw new IllegalStateException("Is not a header."); } } @Override public int categoriesCount() { return mCategories; } } }