Skip to content

Instantly share code, notes, and snippets.

@Marchuck
Created Aug 15, 2015
Embed
What would you like to do?
cos
package pl.sointeractive.smartcity.service;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.util.Log;
import android.view.View;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.orm.query.Condition;
import com.orm.query.Select;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import pl.sointeractive.smartcity.R;
import pl.sointeractive.smartcity.adapters.Draggable.SwipeableStop;
import pl.sointeractive.smartcity.config.Config;
import pl.sointeractive.smartcity.connection.HastInfoWebService;
import pl.sointeractive.smartcity.connection.SimpleRestAdapter;
import pl.sointeractive.smartcity.data.stops.StopNearby;
import pl.sointeractive.smartcity.data.stops.StopNearbyLine;
import pl.sointeractive.smartcity.deserializers.hastinfo.MessagesDeserializer;
import pl.sointeractive.smartcity.deserializers.hastinfo.NextPassingTimesDeserializer;
import pl.sointeractive.smartcity.objects.hastinfo.NextPassingTimes;
import pl.sointeractive.smartcity.objects.otp.StopWithLines;
import pl.sointeractive.smartcity.objects.TripData;
import pl.sointeractive.smartcity.objects.hastinfo.CoupleOfStops;
import pl.sointeractive.smartcity.objects.hastinfo.MessagesListForRoute;
import pl.sointeractive.smartcity.objects.hastinfo.RouteDirectionRecord;
import pl.sointeractive.smartcity.objects.hastinfo.ServiceMessage;
import pl.sointeractive.smartcity.util.TimeManager;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
import retrofit.converter.ConversionException;
import retrofit.converter.GsonConverter;
import rx.Observable;
import rx.Subscriber;
/**
* Created with Lukasz Marczak 10/08/2015
* Name of this class is tricky, but it only contain one big task for thread:
* - downloading all stop nearby
* - downloading all alerts for each line
* - downloading all next passing times for each line for every stop
*/
public class StopsNearbyDataService {
private static final String TAG = StopsNearbyDataService.class.getSimpleName();
private static final String MSG_TAG = MessagesListForRoute.class.getSimpleName();
private static final String NPT_TAG = "NextPassingTimes";
private Activity activity;
private View view;
public static List<String> nextPassingTimesLogger = new LinkedList<>();
public static List<PassingBean> nextPassingTimeData = new LinkedList<>();
public HastInfoWebService nextPassingService;
private static int index = 0;
public StopsNearbyDataService() {
}
public void start(Activity context, View _view) {
activity = context;
view = _view;
setupListForBinding(context);
}
private void setupListForBinding(Activity context) {
Log.d(TAG, "setupListForBinding()");
setupSwipeableStops(context);
if (TripData.swipeableStops == null || TripData.swipeableStops.size() == 0) {
Log.e(TAG, "swipeabe stops error: empty content");
Log.e(NPT_TAG, "swipeabeStops error: empty content");
Log.e(MSG_TAG, "swipeabeStops error: empty content");
return;
}
for (SwipeableStop stop : TripData.swipeableStops) {
String routeIdentifier = stop.getLineNumber();
RouteDirectionRecord routeDirection = Select.from(RouteDirectionRecord.class)
.where(Condition.prop("PUBLIC_IDENTIFIER").eq(routeIdentifier)).first();
Log.i(TAG, "after select: from: " + routeDirection.getDirectionFrom());
Log.i(TAG, "after select: to: " + routeDirection.getDirectionTo());
stop.setRouteDirection(routeDirection);
}
List<SwipeableStop> list = new ArrayList<>();
//usuwamy przystanki ktore maja niestandardowe nazwy kierunkow
for (SwipeableStop stop : TripData.swipeableStops) {
if (stop.getFirstDirection().equals("North") || stop.getFirstDirection().equals("South")
|| stop.getFirstDirection().equals("East") || stop.getFirstDirection().equals("Ouest")
|| stop.getFirstDirection().equals("Est") || stop.getFirstDirection().equals("West")
|| stop.getFirstDirection().equals("Nord") || stop.getFirstDirection().equals("Sud"))
list.add(stop);
}
TripData.swipeableStops = list;
setupAlertMessages();
fetchNextPassingTimes();
}
private void setupSwipeableStops(Context context) {
if (TripData.swipeableStops == null)
TripData.swipeableStops = new ArrayList<>();
TripData.swipeableStops.clear();
String[] nextPassingTimesDummy = new String[]{"-", "-", "-"};
Log.d(TAG, "setupListForBinding()");
if (TripData.stopNearbyStopsList != null && TripData.stopNearbyStopsList.size() > 0
&& TripData.listOfStopWithLines != null && TripData.listOfStopWithLines.size() > 0) {
Log.d(TAG, "listOfStopNearbyLineDataList size = " + TripData.listOfStopWithLines.size());
Log.d(TAG, "stopNearbyStopsList size = " + TripData.stopNearbyStopsList.size());
Log.d(TAG, "Displaying them");
for (StopNearby nearby : TripData.stopNearbyStopsList) {
Log.d(TAG, "nearby: " + nearby.getName() + ", code: " + nearby.getCode());
}
for (StopWithLines nearby : TripData.listOfStopWithLines) {
Log.d(TAG, "content: " + nearby.stopNearby.getName());
}
java.util.List<CoupleOfStops> uniquePairs = new ArrayList<>();
java.util.List<CoupleOfStops> fixedUniquePairs = new ArrayList<>();
/** merging stopWithLines here*/
for (StopWithLines line : TripData.listOfStopWithLines) {
Log.d(TAG, "line with stop nearby" + line.stopNearby.getName());
boolean wasTwin = false;
for (CoupleOfStops previousLine : uniquePairs) {
if (previousLine.first.stopNearby.getName().equals(line.stopNearby.getName())) {
previousLine.second = line;
Log.d(TAG, "updated couple!!! with " + line.stopNearby.getName() + ",id = "
+ line.stopNearby.getId() + ", code = " + line.stopNearby.getCode());
wasTwin = true;
}
}
if (!wasTwin) {
CoupleOfStops c = new CoupleOfStops();
c.first = line;
Log.d(TAG, "adding new couple: " + c.first.stopNearby.getName() + ",id = "
+ line.stopNearby.getId() + ", code = " + c.first.stopNearby.getCode());
uniquePairs.add(c);
}
}
//deleting single stopNearbies
for (CoupleOfStops stops : uniquePairs) {
if (stops.second == null)
Log.d(TAG, "null object here");
else {
fixedUniquePairs.add(stops);
}
}
uniquePairs = fixedUniquePairs;
Log.d(TAG, "unique stopNearby : size = :" + uniquePairs.size());
for (CoupleOfStops mergedStop : uniquePairs) {
Log.d(TAG, "unique pairs: ");
Log.d(TAG, "merged stop first: " + mergedStop.first.stopNearby.getName());
// if (mergedStop.second == null) {
// Log.d(TAG, "second is null! ");
// mergedStop.second = mergedStop.first;
// }
Log.d(TAG, "merged stop second: " + mergedStop.second.stopNearby.getName());
for (StopNearbyLine stopNearbyLine : mergedStop.first.listOfStopNearbyLine) {
StopNearby firstStopNearby = mergedStop.first.stopNearby;
StopNearby secondStopNearby = mergedStop.second.stopNearby;
Log.d(TAG, "adding new stop nearby: ");
Log.d(TAG, "first stop nearby: " + firstStopNearby.getName() + "," + firstStopNearby.getId());
Log.d(TAG, "second stop nearby: " + secondStopNearby.getName() + "," + secondStopNearby.getId());
Log.d(TAG, "linked stop nearby line : " + stopNearbyLine.getLongName()
+ ", number = " + stopNearbyLine.getShortName() + ", id=" + stopNearbyLine.getId() + ", code" + stopNearbyLine.getSTMCode());
SwipeableStop newStop = new SwipeableStop(context, firstStopNearby,
secondStopNearby, stopNearbyLine, nextPassingTimesDummy, nextPassingTimesDummy);
TripData.swipeableStops.add(newStop);
}
}
}
}
private void setupAlertMessages() {
Log.d(TAG, "setupAlertMessages()");
HastInfoWebService webService = new SimpleRestAdapter(Config.HASTINFO_SERVER_URL).getRestAdapter().create(HastInfoWebService.class);
List<Observable<Response>> firstObservableList = new ArrayList<>();
List<Observable<Response>> secondObservableList = new ArrayList<>();
String currentDate = TimeManager.getHastInfoDate();
String audience = "Public";
String includetransitmassage = "Include";
for (SwipeableStop stop : TripData.swipeableStops) {
String routeIdentifier = stop.getLineNumber();
// RouteDirectionRecord routeDirection = Select.from(RouteDirectionRecord.class).where(Condition.prop("PUBLIC_IDENTIFIER").eq(routeIdentifier)).first();
// stop.setRouteDirection(routeDirection);
String directionFirst = SwipeableStop.getfixedDirectioName(stop.getFirstDirection());
String directionSecond = SwipeableStop.getfixedDirectioName(stop.getSecondDirection());
Log.d(TAG, "messages for stop..." + currentDate + "," + audience + "," + includetransitmassage + "," + routeIdentifier + "," + directionFirst);
rx.Observable<Response> firstElement = webService.getMessagesForRoute(currentDate, audience, includetransitmassage, routeIdentifier, directionFirst);
firstObservableList.add(firstElement);
rx.Observable<Response> secondElement = webService.getMessagesForRoute(currentDate, audience, includetransitmassage, routeIdentifier, directionSecond);
secondObservableList.add(secondElement);
}
Observable<Response> firstMaster = Observable.merge(firstObservableList);
Observable<Response> secondMaster = Observable.merge(secondObservableList);
firstMaster.subscribe(getAlertsForSide(true));
secondMaster.subscribe(getAlertsForSide(false));
// List<Observable<Response>> totalObservableList = new ArrayList<>();
// totalObservableList.add(firstMaster);
// totalObservableList.add(secondMaster);
}
private Subscriber<Response> getAlertsForSide(final boolean isFirst) {
return new Subscriber<Response>() {
@Override
public void onCompleted() {
Log.d(TAG, "onCompleted()");
if (isFirst)
TripData.completedAlertsFirst = true;
else
TripData.completedAlertsSecond = true;
}
@Override
public void onNext(Response response) {
Log.d(MSG_TAG, "onNext()");
String url = response.getUrl();
Log.d(MSG_TAG, "url = " + url);
if (response.getBody() == null) {
Log.e(MSG_TAG, "null body of alert");
} else {
Log.e(MSG_TAG, "length of alert" + response.getBody().length());
Type collectionType = new TypeToken<MessagesListForRoute>() {
}.getType();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(collectionType, new MessagesDeserializer());
Gson gson = gsonBuilder.create();
GsonConverter converter = new GsonConverter(gson);
MessagesListForRoute result = null;
try {
result = (MessagesListForRoute) converter.fromBody(response.getBody(), collectionType);
} catch (ConversionException e) {
e.printStackTrace();
Log.d(MSG_TAG, "still null ;(");
} finally {
if (result != null) {
Log.d(MSG_TAG, "result not null");
String query = SimpleRestAdapter.queryExtracter(url, "routeIdentifier");
Log.d(MSG_TAG, "new route identifier: " + query);
for (SwipeableStop stop : TripData.swipeableStops) {
StopNearby stopNearby;
if (isFirst)
stopNearby = stop.getFirstStopNearby();
else
stopNearby = stop.getSecondStopNearby();
// Log.d(TAG, "stopNearby.getId()" + stopNearby.getId());
if (stop.getLineNumber().equals(query)) {
for (ServiceMessage tenTypMes : result.getServiceMessageArrayList()) {
for (String someId : tenTypMes.getStopsIds()) {
// Log.d(TAG, "some Id: " + someId);
if (stopNearby.getId().endsWith(someId)) {
Log.d(TAG, "new alert : " + tenTypMes.getText());
if (isFirst)
stop.setFirstAlertMessage(tenTypMes.getText());
else
stop.setSecondAlertMessage(tenTypMes.getText());
}
}
}
}
}
}
}
}
}
@Override
public void onError(Throwable throwable) {
Log.d(MSG_TAG, "onError()");
throwable.printStackTrace();
TripData.completedAlertsFirst = true;
TripData.completedAlertsSecond = true;
Log.e(MSG_TAG, "onError() downloading alerts...");
if (view != null)
if (view.isShown()) {
Snackbar.make(view, "Failed download notification data", Snackbar.LENGTH_LONG).show();
}
}
};
}
private static String[] DIRECTIONS = {"North", "South", "West", "East"};
private void fetchNextPassingTimes() {
Log.d(TAG, "fetching next passing times()");
nextPassingTimeData.clear();
SimpleRestAdapter nextPassingAdapter = new SimpleRestAdapter(Config.HASTINFO_SERVER_URL);
nextPassingService = nextPassingAdapter.getRestAdapter().create(HastInfoWebService.class);
SharedPreferences sharedPreferences = activity.getSharedPreferences(activity.getString(R.string.shared_preferences_trip_options_key), Context.MODE_PRIVATE);
final String audience = "Public";
final String cultureName = "kn";
final String date = TimeManager.getHastInfoDate();
final String time = TimeManager.getHastInfoTime();
final String serviceMode = "Bus";
final String serviceType = "Regular";
final String routeType = "Regular";
final Boolean isAccessible = sharedPreferences.getBoolean(activity.getString(R.string.shared_preferences_accessible_only), false);
final String maxPassingTimes = "3";
final String maxGap = "100"; //limit do 1h 40min naprzod
final String accessibility = "Any";
// int k = 0;
final List<rx.Observable<Response>> passingObservables = new ArrayList();
for (SwipeableStop stop : TripData.swipeableStops) {
final String lineNumber = stop.getLineNumber();
final String directionFirst = SwipeableStop.getfixedDirectioName(stop.getRouteDirection().getDirectionFrom());
final String directionSecond = SwipeableStop.getfixedDirectioName(stop.getRouteDirection().getDirectionTo());
final String stopIdentifierFrom = stop.getFirstStopNearby().getCode();
final String stopIdentifierTo = stop.getSecondStopNearby().getCode();
Log.d(NPT_TAG, "starting NPT services for lineNumber:" + lineNumber + ",directions: " + directionFirst + "/" + directionSecond);
for (String dre : DIRECTIONS) {
rx.Observable<Response> directioner = nextPassingService.getNextPassingTimes(
cultureName, date, time, stopIdentifierFrom, lineNumber,
dre, serviceMode, serviceType, routeType, isAccessible,
audience, maxPassingTimes, maxGap, accessibility, false)
.onErrorResumeNext(Observable.<Response>empty());
passingObservables.add(directioner);
}
for (String dre : DIRECTIONS) {
rx.Observable<Response> directioner = nextPassingService.getNextPassingTimes(
cultureName, date, time, stopIdentifierTo, lineNumber,
dre, serviceMode, serviceType, routeType, isAccessible,
audience, maxPassingTimes, maxGap, accessibility, false)
.onErrorResumeNext(Observable.<Response>empty());
passingObservables.add(directioner);
}
// fetch_NPT_data(cultureName, date, time, stopIdentifierFrom, lineNumber,
// directionFirst, serviceMode, serviceType, routeType, isAccessible,
// audience, maxPassingTimes, maxGap, accessibility, true);
// fetch_NPT_data(cultureName, date, time, stopIdentifierTo, lineNumber,
// directionSecond, serviceMode, serviceType, routeType, isAccessible,
// audience, maxPassingTimes, maxGap, accessibility, true);
}
Observable<Response> merger = Observable.merge(passingObservables);
merger.subscribe(new Subscriber<Response>() {
@Override
public void onCompleted() {
Log.i(NPT_TAG, "i cant believe its true! " + passings);
// for (PassingBean bean : nextPassingTimeData) {
// for (SwipeableStop stop : TripData.swipeableStops) {
// if (stop.getFirstStopNearby().getCode().equals(bean.code)) {
// if (stop.getLineNumber().equals(bean.lineNumber)) {
// stop.setNextPassingTimesFrom(bean.nextPassingTimes);
// stop.firstDirection = (bean.direction);
// }
// }
// if (stop.getSecondStopNearby().getCode().equals(bean.code)) {
// if (stop.getLineNumber().equals(bean.lineNumber)) {
// stop.setNextPassingTimesTo(bean.nextPassingTimes);
// stop.secondDirection = (bean.direction);
// }
// }
// }
// }
}
@Override
public void onError(Throwable e) {
Log.e(NPT_TAG, "Ooops ;(");
}
@Override
public void onNext(Response response) {
++passings;
if (response.getBody() != null) {
Log.d(NPT_TAG, "onNext(" + passings + "), url = " + response.getUrl());
Log.d(NPT_TAG, "body isn't null. Parsing here");
Type collectionType = new TypeToken<List<NextPassingTimes>>() {
}.getType();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(collectionType, new NextPassingTimesDeserializer());
Gson gson = gsonBuilder.create();
GsonConverter converter = new GsonConverter(gson);
List<NextPassingTimes> result = null;
try {
result = (List<NextPassingTimes>) converter.fromBody(response.getBody(), collectionType);
} catch (ConversionException e) {
e.printStackTrace();
Log.d(NPT_TAG, "still null ;(");
} finally {
if (result != null) {
Log.d(NPT_TAG, "result not null nextpassingtimes");
String url = response.getUrl();
String lineNumber = SimpleRestAdapter.queryExtracter(url, "identifiers");
String code = SimpleRestAdapter.queryExtracter(url, "stopidentifier");
String direction = SimpleRestAdapter.queryExtracter(url, "direction");
int i = 0;
for (SwipeableStop fixedStop : TripData.swipeableStops) {
if (fixedStop.getFirstStopNearby().getCode().equals(code)
|| fixedStop.getSecondStopNearby().getCode().equals(code))
if (lineNumber.equals(fixedStop.getLineNumber())) {
String[] times = new String[]{"", "", ""};
for (int j = 0; j < result.size(); j++) {
Log.d(NPT_TAG, "found stop no. " + i);
Log.d(NPT_TAG, "params: " + j + "," + result.get(j).getTime() + "," + time);
times[j] = result.get(j).getTime();
}
PassingBean bean = new PassingBean();
bean.code = code;
bean.lineNumber = lineNumber;
bean.direction = direction;
bean.nextPassingTimes = times;// new String[]{result.get(0).getTime(), result.get(1).getTime(), result.get(2).getTime()};
nextPassingTimeData.add(bean);
// if(nextPassingTimeData.size()==2*TripData.swipeableStops.size())
// TripData.completedPassingTimes = true;
nextPassingTimesLogger.add(lineNumber
+ "," + bean.nextPassingTimes[0]
+ "," + bean.nextPassingTimes[1]
+ "," + bean.nextPassingTimes[2]
+ "," + code
);
}
++i;
}
}
}
} else {
Log.d(NPT_TAG, "onNext(" + passings + "), url = " + response.getUrl());
Log.d(NPT_TAG, "null body here");
}
}
});
}
private static int passings = 0;
/**
* NPT - next passing times
*
* @param cultureName
* @param date
* @param time
* @param stopIdentifier
* @param lineNumber
* @param direction
* @param serviceMode
* @param serviceType
* @param routeType
* @param isAccessible
* @param audience
* @param maxPassingTimes
* @param maxGap
* @param accessibility
* @param mustRetry - should or should not retry query with reverse direction
*/
private void fetch_NPT_data(final String cultureName,
final String date, final String time, final String stopIdentifier, final String lineNumber,
final String direction, final String serviceMode, final String serviceType,
final String routeType, final Boolean isAccessible, final String audience, final String maxPassingTimes,
final String maxGap, final String accessibility, final boolean mustRetry) {
nextPassingService.getNextPassingTimesRetrofit(cultureName,
date, time, stopIdentifier, lineNumber, direction, serviceMode, serviceType, routeType, isAccessible,
audience, maxPassingTimes, maxGap, accessibility, false, new Callback<Response>() {
@Override
public void success(Response response, Response response2) {
Log.d(NPT_TAG, "success()");
Log.d(NPT_TAG, "url for " + stopIdentifier + ", " + lineNumber + ", " + stopIdentifier + " = " + response.getUrl());
String reverseDirection = getReverseDirection(response.getUrl());
if (response.getBody() == null) {
Log.d(NPT_TAG, "null body!!!");
if (mustRetry)
fetch_NPT_data(cultureName, date, time, stopIdentifier,
lineNumber, reverseDirection, serviceMode, serviceType, routeType,
isAccessible, audience, maxPassingTimes, maxGap, accessibility, false);
} else {
Log.d(NPT_TAG, "get body length: " + response.getBody().length());
Type collectionType = new TypeToken<List<NextPassingTimes>>() {
}.getType();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(collectionType, new NextPassingTimesDeserializer());
Gson gson = gsonBuilder.create();
GsonConverter converter = new GsonConverter(gson);
List<NextPassingTimes> result = null;
try {
result = (List<NextPassingTimes>) converter.fromBody(response.getBody(), collectionType);
} catch (ConversionException e) {
e.printStackTrace();
Log.d(NPT_TAG, "still null ;(");
} finally {
if (result != null) {
Log.d(NPT_TAG, "result not null nextpassingtimes");
String url = response.getUrl();
String lineNumber = SimpleRestAdapter.queryExtracter(url, "identifiers");
String code = SimpleRestAdapter.queryExtracter(url, "stopidentifier");
String direction = SimpleRestAdapter.queryExtracter(url, "direction");
int i = 0;
for (SwipeableStop fixedStop : TripData.swipeableStops) {
if (fixedStop.getFirstStopNearby().getCode().equals(code)
|| fixedStop.getSecondStopNearby().getCode().equals(code))
if (lineNumber.equals(fixedStop.getLineNumber())) {
String[] times = new String[]{"", "", ""};
for (int j = 0; j < result.size(); j++) {
Log.d(NPT_TAG, "found stop no. " + i);
Log.d(NPT_TAG, "params: " + j + "," + result.get(j).getTime() + "," + time);
times[j] = result.get(j).getTime();
}
PassingBean bean = new PassingBean();
bean.code = code;
bean.lineNumber = lineNumber;
bean.direction = direction;
bean.nextPassingTimes = times;// new String[]{result.get(0).getTime(), result.get(1).getTime(), result.get(2).getTime()};
nextPassingTimeData.add(bean);
// if(nextPassingTimeData.size()==2*TripData.swipeableStops.size())
// TripData.completedPassingTimes = true;
nextPassingTimesLogger.add("params for stop number: lineNumber: "
+ lineNumber + ", code: " + code);
nextPassingTimesLogger.add("0:" + times[0]
+ ", 1:" + times[1] + ", 2:" + times[2]);
}
++i;
}
}
}
}
}
@Override
public void failure(RetrofitError error) {
Log.d(NPT_TAG, "failure()");
Log.d(NPT_TAG, "url for " + stopIdentifier + ", " + lineNumber + ", " + direction + " = " + error.getUrl());
Log.d(NPT_TAG, "retrying... ");
// String reverseDirection = getReverseDirection(error.getUrl());
// if (mustRetry)
// fetch_NPT_data(cultureName, date, time, stopIdentifier,
// lineNumber, reverseDirection, serviceMode, serviceType,
// routeType, isAccessible, audience, maxPassingTimes, maxGap, accessibility, false);
}
});
}
@NonNull
private String getReverseDirection(String url) {
String reverse = "null";
Log.d(TAG, "getReverseDirection: ");
if (url.contains("direction=North"))
reverse = "South";
if (url.contains("direction=South"))
reverse = "North";
if (url.contains("direction=East"))
reverse = "West";
if (url.contains("direction=West"))
reverse = "East";
if (reverse.equals("null"))
Log.d(TAG, "unexpected item");
else
Log.d(TAG, "reverse direction is " + reverse);
return reverse;
}
public class PassingBean {
public String[] nextPassingTimes;
public String lineNumber;
public String code;
public String direction;
public PassingBean() {
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment