diff --git a/src/it/reyboz/bustorino/adapters/PalinaAdapter.java b/src/it/reyboz/bustorino/adapters/PalinaAdapter.java --- a/src/it/reyboz/bustorino/adapters/PalinaAdapter.java +++ b/src/it/reyboz/bustorino/adapters/PalinaAdapter.java @@ -32,6 +32,7 @@ import it.reyboz.bustorino.backend.Palina; import it.reyboz.bustorino.backend.Passaggio; import it.reyboz.bustorino.backend.Route; +import it.reyboz.bustorino.backend.utils; /** * This once was a ListView Adapter for BusLine[]. diff --git a/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java b/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java --- a/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java +++ b/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java @@ -20,8 +20,6 @@ // "arrivals" è più usato di "transit" o simili, e chi sono io per mettermi a dibattere con gli inglesi? -import java.util.ArrayList; -import java.util.List; import java.util.concurrent.atomic.AtomicReference; public interface ArrivalsFetcher extends Fetcher { @@ -45,10 +43,10 @@ * @param stopID stop ID, in normalized form. * @param res result code (will be set by this method) * @return arrival times - * @see it.reyboz.bustorino.backend.Fetcher.result + * @see Result * @see FiveTNormalizer */ - Palina ReadArrivalTimesAll(String stopID, AtomicReference<result> res); + Palina ReadArrivalTimesAll(String stopID, AtomicReference<Result> res); /** * Get the determined source for the Fetcher diff --git a/src/it/reyboz/bustorino/backend/Fetcher.java b/src/it/reyboz/bustorino/backend/Fetcher.java --- a/src/it/reyboz/bustorino/backend/Fetcher.java +++ b/src/it/reyboz/bustorino/backend/Fetcher.java @@ -30,7 +30,7 @@ * EMPTY_RESULT_SET: the response is valid and indicates there are no stops\routes\"passaggi"\results for your query<br> * QUERY_TOO_SHORT: input more characters and retry. */ - enum result { + enum Result { OK, CLIENT_OFFLINE, SERVER_ERROR, SETUP_ERROR,PARSER_ERROR, EMPTY_RESULT_SET, QUERY_TOO_SHORT,SERVER_ERROR_404 } } diff --git a/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java b/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java --- a/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java +++ b/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java @@ -37,7 +37,7 @@ final static LinkedList<String> apiDays = new LinkedList<>(Arrays.asList("dom","lun","mar","mer","gio","ven","sab")); @Override - public Palina ReadArrivalTimesAll(String stopID, AtomicReference<result> res) { + public Palina ReadArrivalTimesAll(String stopID, AtomicReference<Result> res) { //set the date for the request as now Palina p = new Palina(stopID); @@ -46,24 +46,19 @@ String response = performAPIRequest(QueryType.ARRIVALS,stopID,res); if(response==null) { - if(res.get()==result.SERVER_ERROR_404) { - Log.w(DEBUG_NAME,"Got 404, either the server failed, or the stop was not found, or the hack is not working anymore"); - res.set(result.EMPTY_RESULT_SET); + if(res.get()== Result.SERVER_ERROR_404) { + Log.w(DEBUG_NAME,"Got 404, either the server failed, or the stop was not found, or the address is wrong"); + res.set(Result.EMPTY_RESULT_SET); } return p; } - try { - List<Route> routes = parseArrivalsServerResponse(response, res); - for(Route r: routes){ + List<Route> routes = parseArrivalsServerResponse(response, res); + if(res.get()==Result.OK) { + for (Route r : routes) { p.addRoute(r); } - } catch (JSONException ex){ - res.set(result.PARSER_ERROR); - Log.w(DEBUG_NAME, "Couldn't get the JSON repr of:\n"+response); - return null; + p.sortRoutes(); } - res.set(result.OK); - p.sortRoutes(); return p; } @@ -72,7 +67,7 @@ return Passaggio.Source.FiveTAPI; } - List<Route> parseArrivalsServerResponse(String JSONresponse, AtomicReference<result> res) throws JSONException{ + List<Route> parseArrivalsServerResponse(String JSONresponse, AtomicReference<Result> res){ ArrayList<Route> routes = new ArrayList<>(3); /* Slight problem: @@ -90,16 +85,20 @@ try{ arr = new JSONArray(JSONresponse); String type; - Route.Type routetype; + Route.Type routetype = Route.Type.UNKNOWN; for(int i =0; i<arr.length();i++){ JSONObject lineJSON = arr.getJSONObject(i); - type = lineJSON.getString("lineType"); String lineName=FiveTNormalizer.routeDisplayToInternal(lineJSON.getString("name")); + if(lineJSON.has("lineType")) { + type = lineJSON.getString("lineType"); + + //set the type of line + if(type.equals("EXTRA")) + routetype = Route.Type.LONG_DISTANCE_BUS; + else routetype = Route.Type.BUS; + } + - //set the type of line - if(type.equals("EXTRA")) - routetype = Route.Type.LONG_DISTANCE_BUS; - else routetype = Route.Type.BUS; //Cut out the spaces in the line Name //temporary fix //lineName = lineName.replace(" ","").replace("/","B"); @@ -120,11 +119,11 @@ } catch (JSONException e) { e.printStackTrace(); - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); return routes; } Collections.sort(routes); - res.set(result.OK); + res.set(Result.OK); return routes; } @@ -143,7 +142,7 @@ continue; } String direction = branchJSON.getString("direction"); - String stops = branchJSON.getJSONObject("branchDetail").getString("stops"); + String lineName = branchJSON.getString("lineName"); Route.Type t = Route.Type.UNKNOWN; //parsing description @@ -190,16 +189,32 @@ festivo = Route.FestiveInfo.FERIALE; } if(t == Route.Type.UNKNOWN &&(lineName.trim().equals("10")|| lineName.trim().equals("15"))) t= Route.Type.TRAM; - if(direction.contains("-")){ + //check for the presence of parenthesis + String preParenthesis, postParenthesis; + boolean hasParenth = false; + if (description.contains("(")){ + hasParenth =true; + preParenthesis = description.split("\\(")[0]; + postParenthesis = description.split("\\(")[1]; + } else { + preParenthesis = description; + postParenthesis = ""; + } + if(preParenthesis.contains("-")){ //Sometimes the actual filtered direction still remains the full line (including both extremes) - direction = direction.split("-")[1]; + preParenthesis = preParenthesis.split("-")[1]; } - Route r = new Route(lineName.trim(),direction.trim(),t,new ArrayList<>()); + final String directionFinal = hasParenth? preParenthesis.trim() + " (" + postParenthesis : preParenthesis; + Route r = new Route(lineName.trim(),directionFinal.trim(),t,new ArrayList<>()); if(serviceDays.length>0) r.serviceDays = serviceDays; r.festivo = festivo; r.branchid = branchid; r.description = description.trim(); - r.setStopsList(Arrays.asList(stops.split(","))); + //check if we have the stop list + if (branchJSON.has("branchDetail")) { + final String stops = branchJSON.getJSONObject("branchDetail").getString("stops"); + r.setStopsList(Arrays.asList(stops.split(","))); + } routes.add(r); } @@ -207,21 +222,21 @@ return routes; } - public List<Route> getDirectionsForStop(String stopID, AtomicReference<result> res) { + public List<Route> getDirectionsForStop(String stopID, AtomicReference<Result> res) { String response = performAPIRequest(QueryType.DETAILS,stopID,res); List<Route> routes; try{ routes = parseDirectionsFromResponse(response); - res.set(result.OK); + res.set(Result.OK); } catch (JSONException | IllegalArgumentException e) { e.printStackTrace(); - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); routes = null; } return routes; } - public ArrayList<Stop> getAllStopsFromGTT(AtomicReference<result> res){ + public ArrayList<Stop> getAllStopsFromGTT(AtomicReference<Result> res){ String response = performAPIRequest(QueryType.STOPS_ALL,null,res); if(response==null) return null; @@ -262,11 +277,11 @@ s.setAbsurdGTTPlaceName(placeName); stopslist.add(s); } - res.set(result.OK); + res.set(Result.OK); } catch (JSONException e) { e.printStackTrace(); - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); return null; } @@ -274,7 +289,7 @@ } @Nullable - public ArrayList<Route> getAllLinesFromGTT(AtomicReference<result> res){ + public ArrayList<Route> getAllLinesFromGTT(AtomicReference<Result> res){ String resp = performAPIRequest(QueryType.LINES,null,res); if(resp==null) { @@ -306,10 +321,10 @@ } //finish - res.set(result.OK); + res.set(Result.OK); } catch (JSONException e) { e.printStackTrace(); - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); return routes; } @@ -336,7 +351,7 @@ * @return a String which contains the result of the query, to be parsed */ @Nullable - public static String performAPIRequest(QueryType t,@Nullable String stopID, AtomicReference<result> res){ + public static String performAPIRequest(QueryType t,@Nullable String stopID, AtomicReference<Result> res){ URL u; Map<String,String> param; @@ -347,7 +362,7 @@ u = new URL(address); } catch (UnsupportedEncodingException |MalformedURLException e) { e.printStackTrace(); - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); return null; } String response = networkTools.queryURL(u,res,param); diff --git a/src/it/reyboz/bustorino/backend/FiveTAPIVolleyRequest.java b/src/it/reyboz/bustorino/backend/FiveTAPIVolleyRequest.java --- a/src/it/reyboz/bustorino/backend/FiveTAPIVolleyRequest.java +++ b/src/it/reyboz/bustorino/backend/FiveTAPIVolleyRequest.java @@ -37,7 +37,7 @@ private ResponseListener listener; final private String url,stopID; - final private AtomicReference<Fetcher.result> resultRef; + final private AtomicReference<Fetcher.Result> resultRef; final private FiveTAPIFetcher fetcher; final private FiveTAPIFetcher.QueryType type; @@ -88,12 +88,12 @@ return Response.error(new VolleyError("Invalid query type")); } } catch (JSONException e) { - resultRef.set(Fetcher.result.PARSER_ERROR); + resultRef.set(Fetcher.Result.PARSER_ERROR); //e.printStackTrace(); Log.w("FivetVolleyParser","JSON Exception in parsing response of: "+url); return Response.error(new ParseError(response)); } - if(resultRef.get()== Fetcher.result.PARSER_ERROR){ + if(resultRef.get()== Fetcher.Result.PARSER_ERROR){ return Response.error(new ParseError(response)); } final Palina p = new Palina(stopID); diff --git a/src/it/reyboz/bustorino/backend/FiveTScraperFetcher.java b/src/it/reyboz/bustorino/backend/FiveTScraperFetcher.java --- a/src/it/reyboz/bustorino/backend/FiveTScraperFetcher.java +++ b/src/it/reyboz/bustorino/backend/FiveTScraperFetcher.java @@ -56,7 +56,7 @@ } @Override - public Palina ReadArrivalTimesAll(final String stopID, final AtomicReference<result> res) { + public Palina ReadArrivalTimesAll(final String stopID, final AtomicReference<Result> res) { Palina p = new Palina(stopID); int routeIndex; @@ -64,7 +64,7 @@ try { responseInDOMFormatBecause5THaveAbsolutelyNoIdeaWhatJSONWas = networkTools.getDOM(new URL("http://www.5t.torino.it/5t/trasporto/arrival-times-byline.jsp?action=getTransitsByLine&shortName=" + URLEncoder.encode(stopID, "utf-8")), res); } catch (Exception e) { - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); } if(responseInDOMFormatBecause5THaveAbsolutelyNoIdeaWhatJSONWas == null) { // result already set in getDOM() @@ -76,28 +76,28 @@ // Tried in rete Edisu (it does Man In The Middle... asd) Element span = doc.select("span").first(); if(span == null) { - res.set(result.SERVER_ERROR); + res.set(Result.SERVER_ERROR); return p; } String busStopID = grep("^(.+) ", span.html()); if (busStopID == null) { //Log.e("BusStop", "Empty busStopID from " + span.html()); - res.set(result.EMPTY_RESULT_SET); + res.set(Result.EMPTY_RESULT_SET); return p; } // this also appears when no stops are found, but that case has already been handled above Element error = doc.select("p.errore").first(); if (error != null) { - res.set(result.SERVER_ERROR); + res.set(Result.SERVER_ERROR); return p; } String busStopName = grep("^.+ (.+)", span.html()); // The first "dot" is the single strange space character in the middle of "39{HERE→} {←HERE}PORTA NUOVA" if (busStopName == null) { //Log.e("BusStop", "Empty busStopName from " + span.html()); - res.set(result.SERVER_ERROR); + res.set(Result.SERVER_ERROR); return p; } p.setStopName(busStopName.trim()); @@ -107,7 +107,7 @@ for (Element tr : trs) { Element line = tr.select("td.line a").first(); if (!line.hasText()) { - res.set(result.SERVER_ERROR); + res.set(Result.SERVER_ERROR); return p; } @@ -121,7 +121,7 @@ // ); if (busLineName == null) { - res.set(result.SERVER_ERROR); + res.set(Result.SERVER_ERROR); return p; } @@ -164,7 +164,7 @@ } p.sortRoutes(); - res.set(result.OK); + res.set(Result.OK); return p; } diff --git a/src/it/reyboz/bustorino/backend/FiveTStopsFetcher.java b/src/it/reyboz/bustorino/backend/FiveTStopsFetcher.java --- a/src/it/reyboz/bustorino/backend/FiveTStopsFetcher.java +++ b/src/it/reyboz/bustorino/backend/FiveTStopsFetcher.java @@ -39,7 +39,7 @@ public class FiveTStopsFetcher implements StopsFinderByName { @Override - public List<Stop> FindByName(String name, AtomicReference<result> res) { + public List<Stop> FindByName(String name, AtomicReference<Result> res) { // API apparently limited to 20 results ArrayList<Stop> busStops = new ArrayList<>(20); String stopID; @@ -48,7 +48,7 @@ //Stop busStop; if(name.length() < 3) { - res.set(result.QUERY_TOO_SHORT); + res.set(Result.QUERY_TOO_SHORT); return busStops; } @@ -57,7 +57,7 @@ try { u = new URL("http://www.5t.torino.it/5t/trasporto/stop-lookup.jsp?action=search&stopShortName=" + URLEncoder.encode(name, "utf-8")); } catch(Exception e) { - res.set(Fetcher.result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); return busStops; } @@ -106,9 +106,9 @@ } if(busStops.size() == 0) { - res.set(result.EMPTY_RESULT_SET); + res.set(Result.EMPTY_RESULT_SET); } else { - res.set(result.OK); + res.set(Result.OK); } Collections.sort(busStops); diff --git a/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java b/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java --- a/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java +++ b/src/it/reyboz/bustorino/backend/GTTJSONFetcher.java @@ -34,7 +34,7 @@ public class GTTJSONFetcher implements ArrivalsFetcher { private final String DEBUG_TAG = "GTTJSONFetcher-BusTO"; @Override @NonNull - public Palina ReadArrivalTimesAll(String stopID, AtomicReference<result> res) { + public Palina ReadArrivalTimesAll(String stopID, AtomicReference<Result> res) { URL url; Palina p = new Palina(stopID); String routename; @@ -48,7 +48,7 @@ try { url = new URL("https://www.gtt.to.it/cms/index.php?option=com_gtt&task=palina.getTransitiOld&palina=" + URLEncoder.encode(stopID, "utf-8") + "&bacino=U&realtime=true&get_param=value"); } catch (Exception e) { - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); return p; } HashMap<String, String> headers = new HashMap<>(); @@ -66,7 +66,7 @@ } catch(JSONException e) { Log.w(DEBUG_TAG, "Error parsing JSON: \n"+content); Log.w(DEBUG_TAG, e); - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); return p; } @@ -76,13 +76,13 @@ json.getJSONObject(0).getString("Linea"); // if we can get this, then there's something useful in the array. } catch(JSONException e) { Log.w(DEBUG_TAG, "No existing lines"); - res.set(result.EMPTY_RESULT_SET); + res.set(Result.EMPTY_RESULT_SET); return p; } howManyRoutes = json.length(); if(howManyRoutes == 0) { - res.set(result.EMPTY_RESULT_SET); + res.set(Result.EMPTY_RESULT_SET); return p; } @@ -115,12 +115,12 @@ } } } catch (JSONException e) { - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); return p; } p.sortRoutes(); - res.set(result.OK); + res.set(Result.OK); return p; } diff --git a/src/it/reyboz/bustorino/backend/GTTStopsFetcher.java b/src/it/reyboz/bustorino/backend/GTTStopsFetcher.java --- a/src/it/reyboz/bustorino/backend/GTTStopsFetcher.java +++ b/src/it/reyboz/bustorino/backend/GTTStopsFetcher.java @@ -33,7 +33,7 @@ public class GTTStopsFetcher implements StopsFinderByName { @Override @NonNull - public List<Stop> FindByName(String name, AtomicReference<result> res) { + public List<Stop> FindByName(String name, AtomicReference<Result> res) { URL url; // sorting an ArrayList should be faster than a LinkedList and the API is limited to 15 results List<Stop> s = new ArrayList<>(15); @@ -48,14 +48,14 @@ JSONObject thisstop; if(name.length() < 3) { - res.set(result.QUERY_TOO_SHORT); + res.set(Result.QUERY_TOO_SHORT); return s; } try { url = new URL("http://www.gtt.to.it/cms/components/com_gtt/views/palinejson/view.html.php?term=" + URLEncoder.encode(name, "utf-8")); } catch (Exception e) { - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); return s; } @@ -69,16 +69,16 @@ } catch(JSONException e) { if(content.contains("[]")) { // when no results are found, server returns a PHP Warning and an empty array. In case they fix the warning, we're looking for the array. - res.set(result.EMPTY_RESULT_SET); + res.set(Result.EMPTY_RESULT_SET); } else { - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); } return s; } howManyStops = json.length(); if(howManyStops == 0) { - res.set(result.EMPTY_RESULT_SET); + res.set(Result.EMPTY_RESULT_SET); return s; } @@ -123,13 +123,13 @@ } } catch (JSONException e) { - res.set(result.PARSER_ERROR); + res.set(Result.PARSER_ERROR); return s; } if(s.size() < 1) { // shouldn't happen but prevents the next part from catching fire - res.set(result.EMPTY_RESULT_SET); + res.set(Result.EMPTY_RESULT_SET); return s; } @@ -137,7 +137,7 @@ // the next loop won't work with less than 2 items if(s.size() < 2) { - res.set(result.OK); + res.set(Result.OK); return s; } @@ -184,7 +184,7 @@ s2.add(s.get(i-1)); } - res.set(result.OK); + res.set(Result.OK); return s2; } diff --git a/src/it/reyboz/bustorino/backend/StopsFinderByName.java b/src/it/reyboz/bustorino/backend/StopsFinderByName.java --- a/src/it/reyboz/bustorino/backend/StopsFinderByName.java +++ b/src/it/reyboz/bustorino/backend/StopsFinderByName.java @@ -29,5 +29,5 @@ * @return list of stops, in normalized form. * @see FiveTNormalizer */ - List<Stop> FindByName(String name, AtomicReference<result> res); + List<Stop> FindByName(String name, AtomicReference<Result> res); } diff --git a/src/it/reyboz/bustorino/backend/StopsFinderByRoute.java b/src/it/reyboz/bustorino/backend/StopsFinderByRoute.java --- a/src/it/reyboz/bustorino/backend/StopsFinderByRoute.java +++ b/src/it/reyboz/bustorino/backend/StopsFinderByRoute.java @@ -29,5 +29,5 @@ * @return list of stops, in normalized form. * @see FiveTNormalizer */ - List<String> FindByRoute(String routeID, StopsDBInterface db, AtomicReference<result> res); + List<String> FindByRoute(String routeID, StopsDBInterface db, AtomicReference<Result> res); } \ No newline at end of file diff --git a/src/it/reyboz/bustorino/backend/networkTools.java b/src/it/reyboz/bustorino/backend/networkTools.java --- a/src/it/reyboz/bustorino/backend/networkTools.java +++ b/src/it/reyboz/bustorino/backend/networkTools.java @@ -33,14 +33,14 @@ import java.util.concurrent.atomic.AtomicReference; public abstract class networkTools { - static String getDOM(final URL url, final AtomicReference<Fetcher.result> res) { + static String getDOM(final URL url, final AtomicReference<Fetcher.Result> res) { //Log.d("asyncwget", "Catching URL in background: " + uri[0]); HttpURLConnection urlConnection; StringBuilder result = null; try { urlConnection = (HttpURLConnection) url.openConnection(); } catch(IOException e) { - res.set(Fetcher.result.SERVER_ERROR); + res.set(Fetcher.Result.SERVER_ERROR); return null; } @@ -63,19 +63,19 @@ } if (result == null) { - res.set(Fetcher.result.SERVER_ERROR); + res.set(Fetcher.Result.SERVER_ERROR); return null; } - res.set(Fetcher.result.PARSER_ERROR); // will be set to "OK" later, this is a safety net in case StringBuilder returns null, the website returns an HTTP 204 or something like that. + res.set(Fetcher.Result.PARSER_ERROR); // will be set to "OK" later, this is a safety net in case StringBuilder returns null, the website returns an HTTP 204 or something like that. return result.toString(); } @Nullable - static String queryURL(URL url, AtomicReference<Fetcher.result> res){ + static String queryURL(URL url, AtomicReference<Fetcher.Result> res){ return queryURL(url,res,null); } @Nullable - static String queryURL(URL url, AtomicReference<Fetcher.result> res, Map<String,String> headers) { + static String queryURL(URL url, AtomicReference<Fetcher.Result> res, Map<String,String> headers) { HttpURLConnection urlConnection; InputStream in; String s; @@ -84,7 +84,7 @@ urlConnection = (HttpURLConnection) url.openConnection(); } catch(IOException e) { //e.printStackTrace(); - res.set(Fetcher.result.SERVER_ERROR); // even when offline, urlConnection works fine. WHY. + res.set(Fetcher.Result.SERVER_ERROR); // even when offline, urlConnection works fine. WHY. return null; } @@ -96,14 +96,14 @@ urlConnection.setRequestProperty(key,headers.get(key)); } } - res.set(Fetcher.result.SERVER_ERROR); // will be set to OK later + res.set(Fetcher.Result.SERVER_ERROR); // will be set to OK later try { in = urlConnection.getInputStream(); } catch (Exception e) { try { if(urlConnection.getResponseCode()==404) - res.set(Fetcher.result.SERVER_ERROR_404); + res.set(Fetcher.Result.SERVER_ERROR_404); } catch (IOException e2) { e2.printStackTrace(); } diff --git a/src/it/reyboz/bustorino/backend/utils.java b/src/it/reyboz/bustorino/backend/utils.java --- a/src/it/reyboz/bustorino/backend/utils.java +++ b/src/it/reyboz/bustorino/backend/utils.java @@ -11,6 +11,7 @@ import java.io.PrintWriter; import java.io.StringWriter; +import java.util.Arrays; public abstract class utils { private static final double EarthRadius = 6371e3; @@ -38,11 +39,13 @@ public static float convertDipToPixels(Context con, float dp){ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,con.getResources().getDisplayMetrics()); } + /* public static int calculateNumColumnsFromSize(View containerView, int pixelsize){ int width = containerView.getWidth(); float ncols = ((float)width)/pixelsize; return (int) Math.floor(ncols); } + */ /** * Check if there is an internet connection @@ -97,6 +100,20 @@ return busStopID; } + public static String toTitleCase(String givenString) { + String[] arr = givenString.split(" "); + StringBuffer sb = new StringBuffer(); + //Log.d("BusTO chars", "String parsing: "+givenString+" in array: "+ Arrays.toString(arr)); + for (int i = 0; i < arr.length; i++) { + if (arr[i].length() > 1) + sb.append(Character.toUpperCase(arr[i].charAt(0))) + .append(arr[i].substring(1)).append(" "); + else sb.append(arr[i]); + } + return sb.toString().trim(); + } + + /** * Open an URL in the default browser. * @@ -106,10 +123,12 @@ Intent browserIntent1 = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); context.startActivity(browserIntent1); } + /** * Print the first i lines of the the trace of an exception * https://stackoverflow.com/questions/21706722/fetch-only-first-n-lines-of-a-stack-trace */ + /* public static String traceCaller(Exception ex, int i) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); @@ -127,4 +146,5 @@ } return "Trace too Short."; } + */ } diff --git a/src/it/reyboz/bustorino/data/DBUpdateWorker.java b/src/it/reyboz/bustorino/data/DBUpdateWorker.java --- a/src/it/reyboz/bustorino/data/DBUpdateWorker.java +++ b/src/it/reyboz/bustorino/data/DBUpdateWorker.java @@ -63,24 +63,24 @@ final Data out = new Data.Builder().putInt(ERROR_REASON_KEY, ERROR_FETCHING_VERSION) .putInt(ERROR_CODE_KEY,new_DB_version).build(); cancelNotification(notificationID); - return Result.failure(out); + return ListenableWorker.Result.failure(out); } //we got a good version if (current_DB_version >= new_DB_version && !isUpdateCompulsory) { //don't need to update cancelNotification(notificationID); - return Result.success(new Data.Builder(). + return ListenableWorker.Result.success(new Data.Builder(). putInt(SUCCESS_REASON_KEY, SUCCESS_NO_ACTION_NEEDED).build()); } //start the real update - AtomicReference<Fetcher.result> resultAtomicReference = new AtomicReference<>(); + AtomicReference<Fetcher.Result> resultAtomicReference = new AtomicReference<>(); DatabaseUpdate.setDBUpdatingFlag(con, shPr,true); final DatabaseUpdate.Result resultUpdate = DatabaseUpdate.performDBUpdate(con,resultAtomicReference); DatabaseUpdate.setDBUpdatingFlag(con, shPr,false); if (resultUpdate != DatabaseUpdate.Result.DONE){ - Fetcher.result result = resultAtomicReference.get(); + Fetcher.Result result = resultAtomicReference.get(); final Data.Builder dataBuilder = new Data.Builder(); switch (resultUpdate){ @@ -92,7 +92,7 @@ break; } cancelNotification(notificationID); - return Result.failure(dataBuilder.build()); + return ListenableWorker.Result.failure(dataBuilder.build()); } Log.d(DEBUG_TAG, "Update finished successfully!"); //update the version in the shared preference @@ -101,7 +101,7 @@ editor.apply(); cancelNotification(notificationID); - return Result.success(new Data.Builder().putInt(SUCCESS_REASON_KEY, SUCCESS_UPDATE_DONE).build()); + return ListenableWorker.Result.success(new Data.Builder().putInt(SUCCESS_REASON_KEY, SUCCESS_UPDATE_DONE).build()); } public static Constraints getWorkConstraints(){ diff --git a/src/it/reyboz/bustorino/data/DatabaseUpdate.java b/src/it/reyboz/bustorino/data/DatabaseUpdate.java --- a/src/it/reyboz/bustorino/data/DatabaseUpdate.java +++ b/src/it/reyboz/bustorino/data/DatabaseUpdate.java @@ -36,7 +36,7 @@ * @return the version of the DB, or an error code */ public static int getNewVersion(){ - AtomicReference<Fetcher.result> gres = new AtomicReference<>(); + AtomicReference<Fetcher.Result> gres = new AtomicReference<>(); String networkRequest = FiveTAPIFetcher.performAPIRequest(FiveTAPIFetcher.QueryType.STOPS_VERSION,null,gres); if(networkRequest == null){ return VERSION_UNAVAILABLE; @@ -57,15 +57,15 @@ * @param gres a result reference * @return result of the update */ - public static Result performDBUpdate(Context con, AtomicReference<Fetcher.result> gres) { + public static Result performDBUpdate(Context con, AtomicReference<Fetcher.Result> gres) { final FiveTAPIFetcher f = new FiveTAPIFetcher(); final ArrayList<Stop> stops = f.getAllStopsFromGTT(gres); //final ArrayList<ContentProviderOperation> cpOp = new ArrayList<>(); - if (gres.get() != Fetcher.result.OK) { + if (gres.get() != Fetcher.Result.OK) { Log.w(DEBUG_TAG, "Something went wrong downloading"); - return Result.ERROR_STOPS_DOWNLOAD; + return DatabaseUpdate.Result.ERROR_STOPS_DOWNLOAD; } // return false; //If the commit to the SharedPreferences didn't succeed, simply stop updating the database @@ -109,7 +109,7 @@ if (routes == null) { Log.w(DEBUG_TAG, "Something went wrong downloading the lines"); dbHelp.close(); - return Result.ERROR_LINES_DOWNLOAD; + return DatabaseUpdate.Result.ERROR_LINES_DOWNLOAD; } @@ -143,7 +143,7 @@ Log.d(DEBUG_TAG, "Inserting lines took: " + ((double) (endTime - startTime) / 1000) + " s"); dbHelp.close(); - return Result.DONE; + return DatabaseUpdate.Result.DONE; } public static boolean setDBUpdatingFlag(Context con, boolean value){ diff --git a/src/it/reyboz/bustorino/data/DatabaseUpdateService.java b/src/it/reyboz/bustorino/data/DatabaseUpdateService.java --- a/src/it/reyboz/bustorino/data/DatabaseUpdateService.java +++ b/src/it/reyboz/bustorino/data/DatabaseUpdateService.java @@ -89,7 +89,7 @@ if(params.mustUpdate || versionDB==-1 || newVersion>versionDB){ Log.d(DEBUG_TAG,"Downloading the bus stops info"); - final AtomicReference<Fetcher.result> gres = new AtomicReference<>(); + final AtomicReference<Fetcher.Result> gres = new AtomicReference<>(); if(!performDBUpdate(gres)) restartDBUpdateifPossible(params,gres); else { @@ -117,7 +117,7 @@ final SharedPreferences shPr = getSharedPreferences(getString(R.string.mainSharedPreferences),MODE_PRIVATE); return setDBUpdatingFlag(shPr,value); } - private boolean performDBUpdate(AtomicReference<Fetcher.result> gres){ + private boolean performDBUpdate(AtomicReference<Fetcher.Result> gres){ if(!setDBUpdatingFlag(true)) return false; @@ -214,7 +214,7 @@ return DatabaseUpdate.performDBUpdate(getApplication(),gres) == DatabaseUpdate.Result.DONE; } private int getNewVersion(UpdateRequestParams params){ - AtomicReference<Fetcher.result> gres = new AtomicReference<>(); + AtomicReference<Fetcher.Result> gres = new AtomicReference<>(); String networkRequest = FiveTAPIFetcher.performAPIRequest(FiveTAPIFetcher.QueryType.STOPS_VERSION,null,gres); if(networkRequest == null){ restartDBUpdateifPossible(params,gres); @@ -231,8 +231,8 @@ return -4; } } - private void restartDBUpdateifPossible(UpdateRequestParams pars, AtomicReference<Fetcher.result> res){ - if (pars.trial<MAX_TRIALS && res.get()!= Fetcher.result.PARSER_ERROR){ + private void restartDBUpdateifPossible(UpdateRequestParams pars, AtomicReference<Fetcher.Result> res){ + if (pars.trial<MAX_TRIALS && res.get()!= Fetcher.Result.PARSER_ERROR){ Log.d(DEBUG_TAG,"Update failed, starting new trial ("+pars.trial+")"); startDBUpdate(getApplicationContext(),++pars.trial,pars.mustUpdate); } diff --git a/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java b/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java --- a/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java +++ b/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java @@ -204,6 +204,10 @@ super.onResume(); LoaderManager loaderManager = getLoaderManager(); Log.d(DEBUG_TAG, "OnResume, justCreated "+justCreated); + /*if(needUpdateOnAttach){ + updateFragmentData(null); + needUpdateOnAttach=false; + }*/ if(stopID!=null){ //refresh the arrivals if(!justCreated){ @@ -228,8 +232,10 @@ super.onStart(); if (needUpdateOnAttach){ updateFragmentData(null); + needUpdateOnAttach = false; } } + @Override public void onPause() { if(listener!=null) diff --git a/src/it/reyboz/bustorino/fragments/FragmentHelper.java b/src/it/reyboz/bustorino/fragments/FragmentHelper.java --- a/src/it/reyboz/bustorino/fragments/FragmentHelper.java +++ b/src/it/reyboz/bustorino/fragments/FragmentHelper.java @@ -185,7 +185,8 @@ if (parameters.addToBackStack) ft.addToBackStack("state_"+parameters.tag); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); - ft.commit(); + if(!fm.isDestroyed()) + ft.commit(); //fm.executePendingTransactions(); } @@ -205,7 +206,7 @@ * Wrapper to show the errors/status that happened * @param res result from Fetcher */ - public void showErrorMessage(Fetcher.result res){ + public void showErrorMessage(Fetcher.Result res){ //TODO: implement a common set of errors for all fragments switch (res){ case OK: diff --git a/src/it/reyboz/bustorino/fragments/MainScreenFragment.java b/src/it/reyboz/bustorino/fragments/MainScreenFragment.java --- a/src/it/reyboz/bustorino/fragments/MainScreenFragment.java +++ b/src/it/reyboz/bustorino/fragments/MainScreenFragment.java @@ -1,3 +1,4 @@ + package it.reyboz.bustorino.fragments; import android.Manifest; diff --git a/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java b/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java --- a/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java +++ b/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java @@ -35,6 +35,7 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.Calendar; @@ -42,13 +43,13 @@ /** * This should be used to download data, but not to display it */ -public class AsyncDataDownload extends AsyncTask<String,Fetcher.result,Object>{ +public class AsyncDataDownload extends AsyncTask<String, Fetcher.Result,Object>{ private static final String TAG = "BusTO-DataDownload"; private static final String DEBUG_TAG = TAG; private boolean failedAll = false; - private final AtomicReference<Fetcher.result> res; + private final AtomicReference<Fetcher.Result> res; private final RequestType t; private String query; WeakReference<FragmentHelper> helperRef; @@ -111,7 +112,7 @@ else if(lastSearchedBusStop!=null) stopID = lastSearchedBusStop.ID; //(it's a Palina) else { - publishProgress(Fetcher.result.QUERY_TOO_SHORT); + publishProgress(Fetcher.Result.QUERY_TOO_SHORT); return null; } //Skip the FiveTAPIFetcher for the Metro Stops because it shows incomprehensible arrival times @@ -119,11 +120,15 @@ continue; p= f.ReadArrivalTimesAll(stopID,res); publishProgress(res.get()); + //if (res.get()!= Fetcher.Result.OK) + Log.d(DEBUG_TAG, "Arrivals fetcher: "+f+"\n\tProgress: "+res.get()); + if(f instanceof FiveTAPIFetcher){ - AtomicReference<Fetcher.result> gres = new AtomicReference<>(); + AtomicReference<Fetcher.Result> gres = new AtomicReference<>(); List<Route> branches = ((FiveTAPIFetcher) f).getDirectionsForStop(stopID,gres); - if(gres.get() == Fetcher.result.OK){ + Log.d(DEBUG_TAG, "FiveTArrivals fetcher: "+f+"\n\tDetails req: "+gres.get()); + if(gres.get() == Fetcher.Result.OK){ p.addInfoFromRoutes(branches); Thread t = new Thread(new BranchInserter(branches, context)); t.start(); @@ -133,7 +138,7 @@ //put updated values into Database } - if(lastSearchedBusStop != null && res.get()== Fetcher.result.OK) { + if(lastSearchedBusStop != null && res.get()== Fetcher.Result.OK) { // check that we don't have the same stop if(lastSearchedBusStop.ID.equals(p.ID)) { // searched and it's the same @@ -160,7 +165,7 @@ result = null; } //find if it went well - if(res.get()== Fetcher.result.OK) { + if(res.get()== Fetcher.Result.OK) { //wait for other threads to finish for(Thread t: otherActivities){ try { @@ -180,10 +185,10 @@ } @Override - protected void onProgressUpdate(Fetcher.result... values) { + protected void onProgressUpdate(Fetcher.Result... values) { FragmentHelper fh = helperRef.get(); if (fh!=null) - for (Fetcher.result r : values){ + for (Fetcher.Result r : values){ //TODO: make Toast fh.showErrorMessage(r); } @@ -270,7 +275,8 @@ @Override public void run() { final NextGenDB nextGenDB = new NextGenDB(context); - ContentValues[] values = new ContentValues[routesToInsert.size()]; + //ContentValues[] values = new ContentValues[routesToInsert.size()]; + ArrayList<ContentValues> branchesValues = new ArrayList<>(routesToInsert.size()*4); ArrayList<ContentValues> connectionsVals = new ArrayList<>(routesToInsert.size()*4); long starttime,endtime; for (Route r:routesToInsert){ @@ -310,22 +316,24 @@ if(r.type!=null) cv.put(BranchesTable.COL_TYPE, r.type.getCode()); cv.put(BranchesTable.COL_FESTIVO, r.festivo.getCode()); - values[routesToInsert.indexOf(r)] = cv; - for(int i=0; i<r.getStopsList().size();i++){ - String stop = r.getStopsList().get(i); - final ContentValues connVal = new ContentValues(); - connVal.put(ConnectionsTable.COLUMN_STOP_ID,stop); - connVal.put(ConnectionsTable.COLUMN_ORDER,i); - connVal.put(ConnectionsTable.COLUMN_BRANCH,r.branchid); - - //add to global connVals - connectionsVals.add(connVal); + //values[routesToInsert.indexOf(r)] = cv; + branchesValues.add(cv); + if(r.getStopsList() != null) + for(int i=0; i<r.getStopsList().size();i++){ + String stop = r.getStopsList().get(i); + final ContentValues connVal = new ContentValues(); + connVal.put(ConnectionsTable.COLUMN_STOP_ID,stop); + connVal.put(ConnectionsTable.COLUMN_ORDER,i); + connVal.put(ConnectionsTable.COLUMN_BRANCH,r.branchid); + + //add to global connVals + connectionsVals.add(connVal); } } starttime = System.currentTimeMillis(); ContentResolver cr = context.getContentResolver(); try { - cr.bulkInsert(Uri.parse("content://" + AppDataProvider.AUTHORITY + "/branches/"), values); + cr.bulkInsert(Uri.parse("content://" + AppDataProvider.AUTHORITY + "/branches/"), branchesValues.toArray(new ContentValues[0])); endtime = System.currentTimeMillis(); Log.d("DataDownload", "Inserted branches, took " + (endtime - starttime) + " ms"); } catch (SQLException exc){ @@ -334,13 +342,14 @@ return; } - - starttime = System.currentTimeMillis(); - ContentValues[] valArr = connectionsVals.toArray(new ContentValues[0]); - Log.d("DataDownloadInsert","inserting "+valArr.length+" connections"); - int rows = nextGenDB.insertBatchContent(valArr,ConnectionsTable.TABLE_NAME); - endtime = System.currentTimeMillis(); - Log.d("DataDownload","Inserted connections found, took "+(endtime-starttime)+" ms, inserted "+rows+" rows"); + if (connectionsVals.size()>0) { + starttime = System.currentTimeMillis(); + ContentValues[] valArr = connectionsVals.toArray(new ContentValues[0]); + Log.d("DataDownloadInsert", "inserting " + valArr.length + " connections"); + int rows = nextGenDB.insertBatchContent(valArr, ConnectionsTable.TABLE_NAME); + endtime = System.currentTimeMillis(); + Log.d("DataDownload", "Inserted connections found, took " + (endtime - starttime) + " ms, inserted " + rows + " rows"); + } nextGenDB.close(); } }