diff --git a/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java b/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java
index 849b3f7..09c4e1c 100644
--- a/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java
+++ b/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java
@@ -1,385 +1,385 @@
/*
BusTO - Backend components
Copyright (C) 2018 Fabio Mazza
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
package it.reyboz.bustorino.backend;
import android.support.annotation.Nullable;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
public class FiveTAPIFetcher implements ArrivalsFetcher{
private static final String SECRET_KEY="759C97DC7D115966C30FD9169BB200D9";
private static final String DEBUG_NAME = "FiveTAPIFetcher";
final static LinkedList apiDays = new LinkedList<>(Arrays.asList("dom","lun","mar","mer","gio","ven","sab"));
@Override
public Palina ReadArrivalTimesAll(String stopID, AtomicReference res) {
//set the date for the request as now
Palina p = new Palina(stopID);
//request parameters
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);
};
return p;
}
/*
Slight problem:
"longName": ==> DESCRIPTION
"name": "13N",
"departures": [
{
"arrivalTimeInt": 1272,
"time": "21:12",
"rt": false
}]
"lineType": "URBANO" ==> URBANO can be either bus or tram or METRO
*/
JSONArray arr;
try{
arr = new JSONArray(response);
String type;
Route.Type routetype;
for(int i =0; i getDirectionsForStop(String stopID, AtomicReference res) {
String response = performAPIRequest(QueryType.DETAILS,stopID,res);
if(response == null) return null;
ArrayList routes = new ArrayList<>(10);
try {
JSONArray lines =new JSONArray(response);
for(int i=0; i 1) {
String secondo = exploded[exploded.length-2];
if (secondo.contains("festivo")) {
festivo = Route.FestiveInfo.FESTIVO;
} else if (secondo.contains("feriale")) {
festivo = Route.FestiveInfo.FERIALE;
} else if(secondo.contains("lun. - ven")) {
serviceDays = Route.reduced_week;
} else if(secondo.contains("sab - fest.")){
serviceDays = Route.weekend;
festivo = Route.FestiveInfo.FESTIVO;
} else {
Log.d(DEBUG_NAME,"Parsing details of line "+lineName+" branchid "+branchid+":\n\t"+
"Couldn't find a the service days\n"+
"Description: "+secondo+","+description
);
}
if(exploded.length>2){
switch (exploded[exploded.length-3].trim()) {
case "bus":
t = Route.Type.BUS;
break;
case "tram":
//never happened, but if it could happen you can get it
t = Route.Type.TRAM;
break;
default:
//nothing
}
}
} else //only one piece
if(description.contains("festivo")){
festivo = Route.FestiveInfo.FESTIVO;
} else if(description.contains("feriale")){
festivo = Route.FestiveInfo.FERIALE;
}
- if(lineName.trim().equals("10")|| lineName.trim().equals("15")) t= Route.Type.TRAM;
+ if(t == null &&(lineName.trim().equals("10")|| lineName.trim().equals("15"))) t= Route.Type.TRAM;
if(direction.contains("-")){
- //
+ //Sometimes the actual filtered direction is instead the full line (including both extremes)
direction = direction.split("-")[1];
}
Route r = new Route(lineName.trim(),direction.trim(),t,null);
if(serviceDays.length>0) r.serviceDays = serviceDays;
r.festivo = festivo;
r.branchid = branchid;
r.description = description.trim();
r.setStopsList(Arrays.asList(stops.split(",")));
routes.add(r);
}
res.set(result.OK);
} catch (JSONException e) {
res.set(result.PARSER_ERROR);
e.printStackTrace();
return null;
}
return routes;
}
public ArrayList getAllStopsFromGTT(AtomicReference res){
String response = performAPIRequest(QueryType.STOPS_ALL,null,res);
if(response==null) return null;
ArrayList stopslist = null;
try{
JSONObject responseJSON = new JSONObject(response);
JSONArray stops = responseJSON.getJSONArray("stops");
stopslist = new ArrayList<>(stops.length());
for (int i=0;i getAllLinesFromGTT(AtomicReference res){
String resp = performAPIRequest(QueryType.LINES,null,res);
if(resp==null) {
return null;
}
ArrayList routes = null;
try {
JSONArray lines = new JSONArray(resp);
routes = new ArrayList<>(lines.length());
for(int i = 0; i res){
Date d = new Date();
URL u;
Hashtable param = new Hashtable<>();
try {
String address = getURLForOperation(t,stopID);
//Log.d(DEBUG_NAME,"The address to query is: "+address);
param.put("TOKEN",getAccessToken(address,d));
param.put("TIMESTAMP",String.valueOf(d.getTime()));
param.put("Accept-Encoding","gzip");
param.put("Connection","Keep-Alive");
u = new URL(address);
} catch (UnsupportedEncodingException | NoSuchAlgorithmException |MalformedURLException e) {
e.printStackTrace();
res.set(result.PARSER_ERROR);
return null;
}
String response = networkTools.queryURL(u,res,param);
return response;
}
/**
* Get the Token needed to access the API
* @param URL the URL of the request
* @return token
* @throws NoSuchAlgorithmException if the system doesn't support MD5
* @throws UnsupportedEncodingException if we made mistakes in writing utf-8
*/
private static String getAccessToken(String URL,Date d) throws NoSuchAlgorithmException,UnsupportedEncodingException{
MessageDigest md = MessageDigest.getInstance("MD5");
String strippedQuery = URL.replace("http://www.5t.torino.it/proxyws","");
//return the time in milliseconds
long timeMilli = d.getTime();
StringBuilder sb = new StringBuilder();
sb.append(strippedQuery);
sb.append(timeMilli);
sb.append(SECRET_KEY);
String stringToBeHashed = sb.toString();
//Log.d(DEBUG_NAME,"Hashing string: "+stringToBeHashed);
md.reset();
byte[] data = md.digest(stringToBeHashed.getBytes("UTF-8"));
sb = new StringBuilder();
for (byte b : data){
sb.append(String.format("%02x",b));
}
String result = sb.toString();
//Log.d(DEBUG_NAME,"getting token:\n\treduced URL: "+strippedQuery+"\n\ttimestamp: "+timeMilli+"\nTOKEN:"+result.toLowerCase());
return result.toLowerCase();
}
/**
* Get the right url for the operation you are doing, to be fed into the queryURL method
* @param t type of operation
* @param stopID stop on which you are working on
* @return the Url to go to
* @throws UnsupportedEncodingException if it cannot be converted to utf-8
*/
private static String getURLForOperation(QueryType t,@Nullable String stopID) throws UnsupportedEncodingException {
final StringBuilder sb = new StringBuilder();
sb.append("http://www.5t.torino.it/proxyws/ws2.1/rest/");
if(t!=QueryType.LINES) sb.append("stops/");
switch (t){
case ARRIVALS:
sb.append(URLEncoder.encode(stopID,"utf-8"));
sb.append("/departures");
break;
case DETAILS:
sb.append(URLEncoder.encode(stopID,"utf-8"));
sb.append("/branches/details");
break;
case STOPS_ALL:
sb.append("all");
break;
case STOPS_VERSION:
sb.append("version");
break;
case LINES:
sb.append("lines/all");
break;
}
return sb.toString();
}
public enum QueryType {
ARRIVALS, DETAILS,STOPS_ALL, STOPS_VERSION,LINES
}
}
diff --git a/src/it/reyboz/bustorino/backend/GlobalStatusPreferences.java b/src/it/reyboz/bustorino/backend/GlobalStatusPreferences.java
index a29dd59..e93a393 100644
--- a/src/it/reyboz/bustorino/backend/GlobalStatusPreferences.java
+++ b/src/it/reyboz/bustorino/backend/GlobalStatusPreferences.java
@@ -1,76 +1,79 @@
/*
BusTO - Backend components
Copyright (C) 2018 Fabio Mazza
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
package it.reyboz.bustorino.backend;
import android.content.Context;
import android.content.SharedPreferences;
+/**
+ * Class to handle app status modifications, e.g. database is being updated or not
+ */
public class GlobalStatusPreferences {
private static final String PREFERENCES_NAME = "it.reyboz.bustorino.statusPreferences";
private static final String DB_UPDATING = "DB_updating";
private Context thecon;
private SharedPreferences preferences;
private SharedPreferences.OnSharedPreferenceChangeListener sharedPrefListener;
public GlobalStatusPreferences(Context thecon) {
this.thecon = thecon;
this.preferences = thecon.getSharedPreferences(PREFERENCES_NAME,Context.MODE_PRIVATE);
}
public boolean isDBUpdating(){
if (preferences == null) preferences = thecon.getSharedPreferences(PREFERENCES_NAME,Context.MODE_PRIVATE);
return preferences.getBoolean(DB_UPDATING,false);
}
public void registerListener(OnDBStatusChangedListener listener){
if(sharedPrefListener!=null) unregisterListener();
sharedPrefListener = new FinishedUpdateListener(listener);
preferences.registerOnSharedPreferenceChangeListener(sharedPrefListener);
}
public void unregisterListener(){
preferences.unregisterOnSharedPreferenceChangeListener(sharedPrefListener);
}
public void setDbUpdating(boolean value){
final SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(DB_UPDATING,value);
editor.apply();
}
/**
* Probably useless
*/
public class FinishedUpdateListener implements SharedPreferences.OnSharedPreferenceChangeListener{
private OnDBStatusChangedListener thingToDo;
public FinishedUpdateListener(OnDBStatusChangedListener thingToDo) {
this.thingToDo = thingToDo;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equals(DB_UPDATING)){
thingToDo.onDBUpdateStatusChanged(sharedPreferences.getBoolean(DB_UPDATING,true));
}
}
}
public interface OnDBStatusChangedListener {
void onDBUpdateStatusChanged(boolean isUpdating);
}
}