package org.mtransit.android.data;
import java.util.ArrayList;
import java.util.HashSet;
import org.json.JSONObject;
import org.mtransit.android.commons.LocationUtils.Area;
import org.mtransit.android.commons.MTLog;
import org.mtransit.android.commons.SqlUtils;
import org.mtransit.android.commons.UriUtils;
import org.mtransit.android.commons.data.AppStatus;
import org.mtransit.android.commons.data.AvailabilityPercent;
import org.mtransit.android.commons.data.News;
import org.mtransit.android.commons.data.POI;
import org.mtransit.android.commons.data.POIStatus;
import org.mtransit.android.commons.data.Route;
import org.mtransit.android.commons.data.Schedule;
import org.mtransit.android.commons.data.ScheduleTimestamps;
import org.mtransit.android.commons.data.ServiceUpdate;
import org.mtransit.android.commons.data.Trip;
import org.mtransit.android.commons.provider.AgencyProviderContract;
import org.mtransit.android.commons.provider.GTFSProviderContract;
import org.mtransit.android.commons.provider.NewsProviderContract;
import org.mtransit.android.commons.provider.POIProvider;
import org.mtransit.android.commons.provider.POIProviderContract;
import org.mtransit.android.commons.provider.ProviderContract;
import org.mtransit.android.commons.provider.ScheduleTimestampsProviderContract;
import org.mtransit.android.commons.provider.ServiceUpdateProviderContract;
import org.mtransit.android.commons.provider.StatusProviderContract;
import android.app.SearchManager;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;
public final class DataSourceManager implements MTLog.Loggable {
private static final String TAG = DataSourceManager.class.getSimpleName();
@Override
public String getLogTag() {
return TAG;
}
private static ArrayMap<String, Uri> uriMap = new ArrayMap<String, Uri>();
private static Uri getUri(String authority) {
Uri uri = uriMap.get(authority);
if (uri == null) {
uri = UriUtils.newContentUri(authority);
uriMap.put(authority, uri);
}
return uri;
}
private DataSourceManager() {
}
public static ArrayList<ServiceUpdate> findServiceUpdates(Context context, String authority, ServiceUpdateProviderContract.Filter serviceUpdateFilter) {
Cursor cursor = null;
try {
String serviceUpdateFilterJSONString = serviceUpdateFilter == null ? null : serviceUpdateFilter.toJSONString();
Uri uri = Uri.withAppendedPath(getUri(authority), ServiceUpdateProviderContract.SERVICE_UPDATE_PATH);
cursor = queryContentResolver(context.getContentResolver(), uri, null, serviceUpdateFilterJSONString, null, null);
return getServiceUpdates(cursor);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
return null;
} finally {
SqlUtils.closeQuietly(cursor);
}
}
private static ArrayList<ServiceUpdate> getServiceUpdates(Cursor cursor) {
ArrayList<ServiceUpdate> result = new ArrayList<ServiceUpdate>();
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
result.add(ServiceUpdate.fromCursor(cursor));
} while (cursor.moveToNext());
}
}
return result;
}
public static News findANews(Context context, String authority, NewsProviderContract.Filter newsFilter) {
ArrayList<News> news = findNews(context, authority, newsFilter);
return news == null || news.size() == 0 ? null : news.get(0);
}
public static ArrayList<News> findNews(Context context, String authority, NewsProviderContract.Filter newsFilter) {
Cursor cursor = null;
try {
String newsFilterJSONString = newsFilter == null ? null : newsFilter.toJSONString();
Uri uri = Uri.withAppendedPath(getUri(authority), NewsProviderContract.NEWS_PATH);
cursor = queryContentResolver(context.getContentResolver(), uri, null, newsFilterJSONString, null, null);
return getNews(cursor, authority);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
return null;
} finally {
SqlUtils.closeQuietly(cursor);
}
}
private static ArrayList<News> getNews(Cursor cursor, String authority) {
ArrayList<News> result = new ArrayList<News>();
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
result.add(News.fromCursorStatic(cursor, authority));
} while (cursor.moveToNext());
}
}
return result;
}
public static ScheduleTimestamps findScheduleTimestamps(Context context, String authority,
ScheduleTimestampsProviderContract.Filter scheduleTimestampsFilter) {
Cursor cursor = null;
try {
String scheduleTimestampsFilterJSONString = scheduleTimestampsFilter == null ? null : scheduleTimestampsFilter.toJSONString();
Uri uri = Uri.withAppendedPath(getUri(authority), ScheduleTimestampsProviderContract.SCHEDULE_TIMESTAMPS_PATH);
cursor = queryContentResolver(context.getContentResolver(), uri, null, scheduleTimestampsFilterJSONString, null, null);
return getScheduleTimestamp(cursor);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
return null;
} finally {
SqlUtils.closeQuietly(cursor);
}
}
private static ScheduleTimestamps getScheduleTimestamp(Cursor cursor) {
ScheduleTimestamps result = null;
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
result = ScheduleTimestamps.fromCursor(cursor);
}
}
return result;
}
public static POIStatus findStatus(Context context, String authority, StatusProviderContract.Filter statusFilter) {
Cursor cursor = null;
try {
String statusFilterJSONString = statusFilter == null ? null : statusFilter.toJSONStringStatic(statusFilter);
Uri uri = Uri.withAppendedPath(getUri(authority), StatusProviderContract.STATUS_PATH);
cursor = queryContentResolver(context.getContentResolver(), uri, null, statusFilterJSONString, null, null);
return getPOIStatus(cursor);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
return null;
} finally {
SqlUtils.closeQuietly(cursor);
}
}
private static POIStatus getPOIStatus(Cursor cursor) {
POIStatus result = null;
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
int status = POIStatus.getTypeFromCursor(cursor);
switch (status) {
case POI.ITEM_STATUS_TYPE_NONE:
result = null;
break;
case POI.ITEM_STATUS_TYPE_SCHEDULE:
result = Schedule.fromCursor(cursor);
break;
case POI.ITEM_STATUS_TYPE_AVAILABILITY_PERCENT:
result = AvailabilityPercent.fromCursor(cursor);
break;
case POI.ITEM_STATUS_TYPE_APP:
result = AppStatus.fromCursor(cursor);
break;
default:
MTLog.w(TAG, "findStatus() > Unexpected status '%s'!", status);
result = null;
break;
}
}
}
return result;
}
public static void ping(Context context, String authority) {
Cursor cursor = null;
try {
Uri uri = Uri.withAppendedPath(getUri(authority), ProviderContract.PING_PATH);
cursor = queryContentResolver(context.getContentResolver(), uri, null, null, null, null);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
} finally {
SqlUtils.closeQuietly(cursor);
}
}
public static AgencyProperties findAgencyProperties(Context context, String authority, DataSourceType dst, boolean isRTS) {
AgencyProperties result = null;
Cursor cursor = null;
try {
Uri uri = Uri.withAppendedPath(getUri(authority), AgencyProviderContract.ALL_PATH);
cursor = queryContentResolver(context.getContentResolver(), uri, null, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
String shortName = cursor.getString(cursor.getColumnIndexOrThrow(AgencyProviderContract.SHORT_NAME_PATH));
String longName = cursor.getString(cursor.getColumnIndexOrThrow(AgencyProviderContract.LABEL_PATH));
String color = cursor.getString(cursor.getColumnIndexOrThrow(AgencyProviderContract.COLOR_PATH));
Area area = Area.fromCursor(cursor);
result = new AgencyProperties(authority, dst, shortName, longName, color, area, isRTS);
}
}
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
} finally {
SqlUtils.closeQuietly(cursor);
}
return result;
}
public static JPaths findAgencyRTSRouteLogo(Context context, String authority) {
JPaths result = null;
Cursor cursor = null;
try {
Uri uri = Uri.withAppendedPath(getUri(authority), GTFSProviderContract.ROUTE_LOGO_PATH);
cursor = queryContentResolver(context.getContentResolver(), uri, null, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
result = JPaths.fromJSONString(cursor.getString(0));
}
}
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
} finally {
SqlUtils.closeQuietly(cursor);
}
return result;
}
public static Trip findRTSTrip(Context context, String authority, int tripId) {
Cursor cursor = null;
try {
Uri uri = getRTSTripsUri(authority);
String selection = SqlUtils.getWhereEquals(GTFSProviderContract.TripColumns.T_TRIP_K_ID, tripId);
cursor = queryContentResolver(context.getContentResolver(), uri, GTFSProviderContract.PROJECTION_TRIP, selection, null, null);
ArrayList<Trip> rtsTrips = getRTSTrips(cursor);
return rtsTrips == null || rtsTrips.size() == 0 ? null : rtsTrips.get(0);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
return null;
} finally {
SqlUtils.closeQuietly(cursor);
}
}
public static ArrayList<Trip> findRTSRouteTrips(Context context, String authority, long routeId) {
Cursor cursor = null;
try {
Uri uri = getRTSTripsUri(authority);
String selection = SqlUtils.getWhereEquals(GTFSProviderContract.TripColumns.T_TRIP_K_ROUTE_ID, routeId);
cursor = queryContentResolver(context.getContentResolver(), uri, GTFSProviderContract.PROJECTION_TRIP, selection, null, null);
return getRTSTrips(cursor);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
return null;
} finally {
SqlUtils.closeQuietly(cursor);
}
}
private static ArrayList<Trip> getRTSTrips(Cursor cursor) {
ArrayList<Trip> result = new ArrayList<Trip>();
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
Trip fromCursor = Trip.fromCursor(cursor);
result.add(fromCursor);
} while (cursor.moveToNext());
}
}
return result;
}
public static Route findRTSRoute(Context context, String authority, long routeId) {
Cursor cursor = null;
try {
Uri uri = getRTSRoutesUri(authority);
String selection = SqlUtils.getWhereEquals(GTFSProviderContract.RouteColumns.T_ROUTE_K_ID, routeId);
cursor = queryContentResolver(context.getContentResolver(), uri, GTFSProviderContract.PROJECTION_ROUTE, selection, null, null);
ArrayList<Route> rtsRoutes = getRTSRoutes(cursor);
return rtsRoutes == null || rtsRoutes.size() == 0 ? null : rtsRoutes.get(0);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
return null;
} finally {
SqlUtils.closeQuietly(cursor);
}
}
public static Cursor queryContentResolver(ContentResolver contentResolver, Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
return contentResolver.query(uri, projection, selection, selectionArgs, sortOrder);
}
public static ArrayList<Route> findAllRTSAgencyRoutes(Context context, String authority) {
Cursor cursor = null;
try {
Uri uri = getRTSRoutesUri(authority);
cursor = queryContentResolver(context.getContentResolver(), uri, GTFSProviderContract.PROJECTION_ROUTE, null, null, null);
return getRTSRoutes(cursor);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
return null;
} finally {
SqlUtils.closeQuietly(cursor);
}
}
private static ArrayList<Route> getRTSRoutes(Cursor cursor) {
ArrayList<Route> result = new ArrayList<Route>();
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
Route fromCursor = Route.fromCursor(cursor);
result.add(fromCursor);
} while (cursor.moveToNext());
}
}
return result;
}
public static POIManager findPOI(Context context, String authority, POIProviderContract.Filter poiFilter) {
ArrayList<POIManager> pois = findPOIs(context, authority, poiFilter);
return pois == null || pois.size() == 0 ? null : pois.get(0);
}
public static ArrayList<POIManager> findPOIs(Context context, String authority, POIProviderContract.Filter poiFilter) {
Cursor cursor = null;
try {
JSONObject filterJSON = POIProviderContract.Filter.toJSON(poiFilter);
if (filterJSON == null) {
MTLog.w(TAG, "Invalid POI filter!");
return null;
}
String filterJsonString = filterJSON.toString();
Uri uri = getPOIUri(authority);
cursor = queryContentResolver(context.getContentResolver(), uri, POIProvider.PROJECTION_POI_ALL_COLUMNS, filterJsonString, null, null);
return getPOIs(cursor, authority);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
return null;
} finally {
SqlUtils.closeQuietly(cursor);
}
}
private static ArrayList<POIManager> getPOIs(Cursor cursor, String authority) {
ArrayList<POIManager> result = new ArrayList<POIManager>();
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
result.add(POIManager.fromCursorStatic(cursor, authority));
} while (cursor.moveToNext());
}
}
return result;
}
public static HashSet<String> findSearchSuggest(Context context, String authority, String query) {
Cursor cursor = null;
try {
Uri searchSuggestUri = Uri.withAppendedPath(getUri(authority), SearchManager.SUGGEST_URI_PATH_QUERY);
if (!TextUtils.isEmpty(query)) {
searchSuggestUri = Uri.withAppendedPath(searchSuggestUri, Uri.encode(query));
}
cursor = queryContentResolver(context.getContentResolver(), searchSuggestUri, null, null, null, null);
return getSearchSuggest(cursor);
} catch (Exception e) {
MTLog.w(TAG, e, "Error!");
return null;
} finally {
SqlUtils.closeQuietly(cursor);
}
}
public static HashSet<String> getSearchSuggest(Cursor cursor) {
HashSet<String> results = new HashSet<String>();
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
int text1ColumnIdx = cursor.getColumnIndexOrThrow(SearchManager.SUGGEST_COLUMN_TEXT_1);
do {
String suggest = cursor.getString(text1ColumnIdx);
results.add(suggest);
} while (cursor.moveToNext());
}
}
return results;
}
private static Uri getPOIUri(String authority) {
return Uri.withAppendedPath(getUri(authority), POIProviderContract.POI_PATH);
}
private static Uri getRTSRoutesUri(String authority) {
return Uri.withAppendedPath(getUri(authority), GTFSProviderContract.ROUTE_PATH);
}
private static Uri getRTSTripsUri(String authority) {
return Uri.withAppendedPath(getUri(authority), GTFSProviderContract.TRIP_PATH);
}
}