/**
* Copyright (c) 2011 Christine Gerpheide <christine.ger@pheide.com>
*
* This code is distributed under the MIT License. Please see LICENSE.txt
* for more details.
*/
package com.pheide.trainose;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.database.Cursor;
import android.widget.Toast;
/**
* Class to handle synchronizing the timetables for a route.
*
* Typically run in the background.
*
* @author Christine Gerpheide
*/
public class TimetablesSynchronizer {
Activity mActivity; // Needed for context and cursor management
List<HashMap<String,String>> mTimetablesList = null;
/**
* Construct the synchronizer.
*
* @param activity to use for context and cursor management.
*/
public TimetablesSynchronizer(Activity activity) {
mActivity = activity;
}
/**
* Download and store all timetables for a given route.
*
* @param long the route ID for which to download timetables.
* @return
*/
public Boolean syncTimetablesForRoute(long routeId) {
try {
// Get details (to/from) for this route
RoutesDbAdapter routesDbAdapter = new RoutesDbAdapter(mActivity);
routesDbAdapter.open();
Cursor routesCursor = routesDbAdapter.fetch(routeId);
mActivity.startManagingCursor(routesCursor);
String source = CursorHelper.getString(routesCursor,RoutesDbAdapter.KEY_SOURCE);
String destination = CursorHelper.getString(routesCursor,RoutesDbAdapter.KEY_DESTINATION);
mActivity.stopManagingCursor(routesCursor);
routesDbAdapter.close();
// Retrieve JSON from server
URL sourceUrl = new URL("http://www.pheide.com/Services/TrainOse/ose_json.php?"
+ "from=" + URLEncoder.encode(source,"UTF-8")
+ "&to=" + URLEncoder.encode(destination,"UTF-8"));
BufferedReader in = new BufferedReader(new InputStreamReader(
sourceUrl.openStream()));
String inputLine;
String jsonStr = "";
while ((inputLine = in.readLine()) != null)
jsonStr = jsonStr + inputLine;
in.close();
JSONObject jsonObj = new JSONObject(jsonStr);
// Clear current timetables and add the new ones
JSONArray routes = (JSONArray) jsonObj.get("routes");
if (routes.length() > 0) {
TimetablesDbAdapter timetablesDbAdapter = new TimetablesDbAdapter(mActivity);
timetablesDbAdapter.open();
timetablesDbAdapter.deleteByRoute(routeId);
LegsDbAdapter legsDbAdapter = new LegsDbAdapter(mActivity);
legsDbAdapter.open();
for (int i = 0; i < routes.length(); i++) {
JSONObject route = routes.getJSONObject(i);
JSONArray legs = (JSONArray) route.get("legs");
// Create the route, with some values from the legs for convenience
int numLegs = legs.length();
JSONObject firstLeg = legs.getJSONObject(0); // one should always exist
long timetableId = timetablesDbAdapter.create(routeId,
firstLeg.getString("depart"),
legs.getJSONObject(numLegs - 1).getString("arrive"), // last leg
route.getString("duration"),
firstLeg.getString("train"),
firstLeg.getString("trainNum"), numLegs,
firstLeg.getString("delay"));
// Add legs for this timetable
legsDbAdapter.deleteByTimetable(timetableId);
for (int j = 0; j < legs.length(); j++) {
JSONObject leg = legs.getJSONObject(j);
legsDbAdapter.create(timetableId, leg.getString("depart"),
leg.getString("arrive"), leg.getString("train"),
leg.getString("trainNum"),leg.getString("delay"),
leg.getString("source"),leg.getString("destination"));
}
}
legsDbAdapter.close();
timetablesDbAdapter.close();
}
// Update date last synced for this route
routesDbAdapter.open();
routesDbAdapter.touchTimestamp(routeId);
routesDbAdapter.close();
} catch (IOException e) { // Couldn't reach host
mActivity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(mActivity, mActivity.getString(R.string.exception_network), Toast.LENGTH_LONG).show();
}
});
} catch (JSONException e) { // JSON empty or not formatted
mActivity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(mActivity, mActivity.getString(R.string.exception_server), Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) { // Something else. Hmm...
mActivity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(mActivity, mActivity.getString(R.string.exception), Toast.LENGTH_LONG).show();
}
});
}
return true;
}
}