Changeset View
Changeset View
Standalone View
Standalone View
src/it/reyboz/bustorino/middleware/AsyncArrivalsSearcher.java
- This file was moved from src/it/reyboz/bustorino/middleware/AsyncDataDownload.java.
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.concurrent.atomic.AtomicReference; | import java.util.concurrent.atomic.AtomicReference; | ||||
import java.util.Calendar; | import java.util.Calendar; | ||||
/** | /** | ||||
* This should be used to download data, but not to display it | * This should be used to download data, but not to display it | ||||
*/ | */ | ||||
public class AsyncDataDownload extends AsyncTask<String, Fetcher.Result,Object>{ | public class AsyncArrivalsSearcher extends AsyncTask<String, Fetcher.Result,Palina>{ | ||||
private static final String TAG = "BusTO-DataDownload"; | private static final String TAG = "BusTO-DataDownload"; | ||||
private static final String DEBUG_TAG = TAG; | private static final String DEBUG_TAG = TAG; | ||||
private boolean failedAll = false; | private boolean failedAll = false; | ||||
private final AtomicReference<Fetcher.Result> res; | private final AtomicReference<Fetcher.Result> res; | ||||
private final RequestType t; | |||||
private String query; | private String query; | ||||
WeakReference<FragmentHelper> helperRef; | WeakReference<FragmentHelper> helperRef; | ||||
private final ArrayList<Thread> otherActivities = new ArrayList<>(); | private final ArrayList<Thread> otherActivities = new ArrayList<>(); | ||||
private final Fetcher[] theFetchers; | private final ArrivalsFetcher[] theFetchers; | ||||
@SuppressLint("StaticFieldLeak") | @SuppressLint("StaticFieldLeak") | ||||
private final Context context; | private final Context context; | ||||
private final boolean replaceFragment; | private final boolean replaceFragment; | ||||
public AsyncDataDownload(FragmentHelper fh, @NonNull Fetcher[] fetchers, Context context) { | public AsyncArrivalsSearcher(FragmentHelper fh, @NonNull ArrivalsFetcher[] fetchers, Context context) { | ||||
RequestType type; | |||||
helperRef = new WeakReference<>(fh); | helperRef = new WeakReference<>(fh); | ||||
fh.setLastTaskRef(new WeakReference<>(this)); | fh.setLastTaskRef(this); | ||||
res = new AtomicReference<>(); | res = new AtomicReference<>(); | ||||
this.context = context.getApplicationContext(); | this.context = context.getApplicationContext(); | ||||
this.replaceFragment = true; | this.replaceFragment = true; | ||||
theFetchers = fetchers; | theFetchers = fetchers; | ||||
if (theFetchers.length < 1){ | if (theFetchers.length < 1){ | ||||
throw new IllegalArgumentException("You have to put at least one Fetcher, idiot!"); | throw new IllegalArgumentException("You have to put at least one Fetcher, idiot!"); | ||||
} | } | ||||
if (theFetchers[0] instanceof ArrivalsFetcher){ | |||||
type = RequestType.ARRIVALS; | |||||
} else if (theFetchers[0] instanceof StopsFinderByName){ | |||||
type = RequestType.STOPS; | |||||
} else{ | |||||
type = null; | |||||
} | |||||
t = type; | |||||
} | } | ||||
@Override | @Override | ||||
protected Object doInBackground(String... params) { | protected Palina doInBackground(String... params) { | ||||
RecursionHelper<Fetcher> r = new RecursionHelper<>(theFetchers); | RecursionHelper<ArrivalsFetcher> r = new RecursionHelper<>(theFetchers); | ||||
boolean success=false; | Palina result = null; | ||||
Object result; | |||||
FragmentHelper fh = helperRef.get(); | FragmentHelper fh = helperRef.get(); | ||||
ArrayList<Fetcher.Result> results = new ArrayList<>(theFetchers.length); | ArrayList<Fetcher.Result> results = new ArrayList<>(theFetchers.length); | ||||
//If the FragmentHelper is null, that means the activity doesn't exist anymore | //If the FragmentHelper is null, that means the activity doesn't exist anymore | ||||
if (fh == null){ | if (fh == null){ | ||||
return null; | return null; | ||||
} | } | ||||
//Log.d(TAG,"refresh layout reference is: "+fh.isRefreshLayoutReferenceTrue()); | //Log.d(TAG,"refresh layout reference is: "+fh.isRefreshLayoutReferenceTrue()); | ||||
while(r.valid()) { | while(r.valid()) { | ||||
if(this.isCancelled()) { | if(this.isCancelled()) { | ||||
return null; | return null; | ||||
} | } | ||||
//get the data from the fetcher | //get the data from the fetcher | ||||
switch (t){ | ArrivalsFetcher f = r.getAndMoveForward(); | ||||
case ARRIVALS: | AtomicReference<Fetcher.Result> resRef = new AtomicReference<>(); | ||||
ArrivalsFetcher f = (ArrivalsFetcher) r.getAndMoveForward(); | |||||
if (f instanceof MatoAPIFetcher){ | if (f instanceof MatoAPIFetcher){ | ||||
((MatoAPIFetcher)f).setAppContext(context); | ((MatoAPIFetcher)f).setAppContext(context); | ||||
} | } | ||||
Log.d(TAG,"Using the ArrivalsFetcher: "+f.getClass()); | Log.d(TAG,"Using the ArrivalsFetcher: "+f.getClass()); | ||||
Stop lastSearchedBusStop = fh.getLastSuccessfullySearchedBusStop(); | Stop lastSearchedBusStop = fh.getLastSuccessfullySearchedBusStop(); | ||||
Palina p; | Palina p; | ||||
String stopID; | String stopID; | ||||
if(params.length>0) | if(params.length>0) | ||||
stopID=params[0]; //(it's a Palina) | stopID=params[0]; //(it's a Palina) | ||||
else if(lastSearchedBusStop!=null) | else if(lastSearchedBusStop!=null) | ||||
stopID = lastSearchedBusStop.ID; //(it's a Palina) | stopID = lastSearchedBusStop.ID; //(it's a Palina) | ||||
else { | else { | ||||
publishProgress(Fetcher.Result.QUERY_TOO_SHORT); | publishProgress(Fetcher.Result.QUERY_TOO_SHORT); | ||||
return null; | return null; | ||||
} | } | ||||
//Skip the FiveTAPIFetcher for the Metro Stops because it shows incomprehensible arrival times | //Skip the FiveTAPIFetcher for the Metro Stops because it shows incomprehensible arrival times | ||||
try { | try { | ||||
if (f instanceof FiveTAPIFetcher && Integer.parseInt(stopID) >= 8200) | if (f instanceof FiveTAPIFetcher && Integer.parseInt(stopID) >= 8200) | ||||
continue; | continue; | ||||
} catch (NumberFormatException ex){ | } catch (NumberFormatException ex){ | ||||
Log.e(DEBUG_TAG, "The stop number is not a valid integer, expect failures"); | Log.e(DEBUG_TAG, "The stop number is not a valid integer, expect failures"); | ||||
} | } | ||||
p= f.ReadArrivalTimesAll(stopID,res); | p= f.ReadArrivalTimesAll(stopID,resRef); | ||||
//if (res.get()!= Fetcher.Result.OK) | |||||
Log.d(DEBUG_TAG, "Arrivals fetcher: "+f+"\n\tProgress: "+res.get()); | |||||
//if (res.get()!= Fetcher.Result.OK) | |||||
Log.d(DEBUG_TAG, "Arrivals fetcher: "+f+"\n\tProgress: "+resRef.get()); | |||||
if(f instanceof FiveTAPIFetcher){ | if(f instanceof FiveTAPIFetcher){ | ||||
AtomicReference<Fetcher.Result> gres = new AtomicReference<>(); | AtomicReference<Fetcher.Result> gres = new AtomicReference<>(); | ||||
List<Route> branches = ((FiveTAPIFetcher) f).getDirectionsForStop(stopID,gres); | List<Route> branches = ((FiveTAPIFetcher) f).getDirectionsForStop(stopID,gres); | ||||
Log.d(DEBUG_TAG, "FiveTArrivals fetcher: "+f+"\n\tDetails req: "+gres.get()); | Log.d(DEBUG_TAG, "FiveTArrivals fetcher: "+f+"\n\tDetails req: "+gres.get()); | ||||
if(gres.get() == Fetcher.Result.OK){ | if(gres.get() == Fetcher.Result.OK){ | ||||
p.addInfoFromRoutes(branches); | p.addInfoFromRoutes(branches); | ||||
Thread t = new Thread(new BranchInserter(branches, context)); | Thread t = new Thread(new BranchInserter(branches, context)); | ||||
t.start(); | t.start(); | ||||
otherActivities.add(t); | otherActivities.add(t); | ||||
} else{ | |||||
resRef.set(Fetcher.Result.NOT_FOUND); | |||||
} | } | ||||
//put updated values into Database | //put updated values into Database | ||||
} | } | ||||
if(lastSearchedBusStop != null && res.get()== Fetcher.Result.OK) { | if(lastSearchedBusStop != null && resRef.get()== Fetcher.Result.OK) { | ||||
// check that we don't have the same stop | // check that we don't have the same stop | ||||
if(lastSearchedBusStop.ID.equals(p.ID)) { | if(lastSearchedBusStop.ID.equals(p.ID)) { | ||||
// searched and it's the same | // searched and it's the same | ||||
String sn = lastSearchedBusStop.getStopDisplayName(); | String sn = lastSearchedBusStop.getStopDisplayName(); | ||||
if(sn != null) { | if(sn != null) { | ||||
// "merge" Stop over Palina and we're good to go | // "merge" Stop over Palina and we're good to go | ||||
p.mergeNameFrom(lastSearchedBusStop); | p.mergeNameFrom(lastSearchedBusStop); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
p.mergeDuplicateRoutes(0); | p.mergeDuplicateRoutes(0); | ||||
if (p.getTotalNumberOfPassages() == 0) | if (resRef.get() == Fetcher.Result.OK && p.getTotalNumberOfPassages() == 0 ) { | ||||
res.set(Fetcher.Result.EMPTY_RESULT_SET); | resRef.set(Fetcher.Result.EMPTY_RESULT_SET); | ||||
publishProgress(res.get()); | Log.d(DEBUG_TAG, "Setting empty results"); | ||||
//p.sortRoutes(); | } | ||||
result = p; | publishProgress(resRef.get()); | ||||
//TODO: find a way to avoid overloading the user with toasts | //TODO: find a way to avoid overloading the user with toasts | ||||
break; | if (result == null){ | ||||
case STOPS: | result = p; | ||||
StopsFinderByName finder = (StopsFinderByName) r.getAndMoveForward(); | |||||
List<Stop> resultList= finder.FindByName(params[0], this.res); //it's a List<Stop> | |||||
Log.d(TAG,"Using the StopFinderByName: "+finder.getClass()); | |||||
query =params[0]; | |||||
result = resultList; //dummy result | |||||
Log.d(DEBUG_TAG, "Result: "+res.get()+", "+resultList.size()+" stops"); | |||||
break; | |||||
default: | |||||
result = null; | |||||
} | } | ||||
//find if it went well | //find if it went well | ||||
results.add(res.get()); | results.add(resRef.get()); | ||||
if(res.get()== Fetcher.Result.OK) { | if(resRef.get()== Fetcher.Result.OK) { | ||||
//wait for other threads to finish | //wait for other threads to finish | ||||
for(Thread t: otherActivities){ | for(Thread t: otherActivities){ | ||||
try { | try { | ||||
t.join(); | t.join(); | ||||
} catch (InterruptedException e) { | } catch (InterruptedException e) { | ||||
//do nothing | //do nothing | ||||
} | } | ||||
} | } | ||||
return result; | return p; | ||||
} | } | ||||
} | } | ||||
boolean emptyResults = true; | boolean emptyResults = true; | ||||
for (Fetcher.Result re: results){ | for (Fetcher.Result re: results){ | ||||
if (!re.equals(Fetcher.Result.EMPTY_RESULT_SET)) { | if (!re.equals(Fetcher.Result.EMPTY_RESULT_SET)) { | ||||
emptyResults = false; | emptyResults = false; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if(emptyResults){ | |||||
if(t==RequestType.STOPS) | |||||
publishProgress(Fetcher.Result.EMPTY_RESULT_SET); | |||||
} | |||||
//at this point, we are sure that the result has been negative | //at this point, we are sure that the result has been negative | ||||
failedAll=true; | failedAll=true; | ||||
return null; | return result; | ||||
} | } | ||||
@Override | @Override | ||||
protected void onProgressUpdate(Fetcher.Result... values) { | protected void onProgressUpdate(Fetcher.Result... values) { | ||||
FragmentHelper fh = helperRef.get(); | FragmentHelper fh = helperRef.get(); | ||||
if (fh!=null) | if (fh!=null) | ||||
for (Fetcher.Result r : values){ | for (Fetcher.Result r : values){ | ||||
//TODO: make Toast | //TODO: make Toast | ||||
fh.showErrorMessage(r); | fh.showErrorMessage(r, SearchRequestType.ARRIVALS); | ||||
} | } | ||||
else { | else { | ||||
Log.w(TAG,"We had to show some progress but activity was destroyed"); | Log.w(TAG,"We had to show some progress but activity was destroyed"); | ||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
protected void onPostExecute(Object o) { | protected void onPostExecute(Palina p) { | ||||
FragmentHelper fh = helperRef.get(); | FragmentHelper fh = helperRef.get(); | ||||
if(failedAll || o == null || fh == null){ | if(failedAll || p == null || fh == null){ | ||||
//everything went bad | //everything went bad | ||||
if(fh!=null) fh.toggleSpinner(false); | if(fh!=null) fh.toggleSpinner(false); | ||||
cancel(true); | cancel(true); | ||||
//TODO: send message here | //TODO: send message here | ||||
return; | return; | ||||
} | } | ||||
if(isCancelled()) return; | if(isCancelled()) return; | ||||
switch (t){ | |||||
case ARRIVALS: | fh.createOrUpdateStopFragment( p, replaceFragment); | ||||
Palina palina = (Palina) o; | |||||
fh.createOrUpdateStopFragment(palina, replaceFragment); | |||||
break; | |||||
case STOPS: | |||||
//this should never be a problem | |||||
if(!(o instanceof List<?>)){ | |||||
throw new IllegalStateException(); | |||||
} | |||||
List<?> list = (List<?>) o; | |||||
if (list.size() ==0) return; | |||||
Object firstItem = list.get(0); | |||||
if(!(firstItem instanceof Stop)) return; | |||||
ArrayList<Stop> stops = new ArrayList<>(); | |||||
for(Object x: list){ | |||||
if(x instanceof Stop) stops.add((Stop) x); | |||||
//Log.d(DEBUG_TAG, "Parsing Stop: "+x); | |||||
} | |||||
if(list.size() != stops.size()){ | |||||
Log.w(DEBUG_TAG, "Wrong stop list size:\n incoming: "+ | |||||
list.size()+" out: "+stops.size()); | |||||
} | |||||
//List<Stop> stopList = (List<Stop>) list; | |||||
if(query!=null && !isCancelled()) { | |||||
fh.createStopListFragment(stops,query, replaceFragment); | |||||
} else Log.e(TAG,"QUERY NULL, COULD NOT CREATE FRAGMENT"); | |||||
break; | |||||
case DBUPDATE: | |||||
break; | |||||
} | |||||
} | } | ||||
@Override | @Override | ||||
protected void onCancelled() { | protected void onCancelled() { | ||||
FragmentHelper fh = helperRef.get(); | FragmentHelper fh = helperRef.get(); | ||||
if (fh!=null) fh.toggleSpinner(false); | if (fh!=null) fh.toggleSpinner(false); | ||||
} | } | ||||
@Override | @Override | ||||
protected void onPreExecute() { | protected void onPreExecute() { | ||||
FragmentHelper fh = helperRef.get(); | FragmentHelper fh = helperRef.get(); | ||||
if (fh!=null) fh.toggleSpinner(true); | if (fh!=null) fh.toggleSpinner(true); | ||||
} | } | ||||
public enum RequestType { | |||||
ARRIVALS,STOPS,DBUPDATE | |||||
} | |||||
public static class BranchInserter implements Runnable{ | public static class BranchInserter implements Runnable{ | ||||
private final List<Route> routesToInsert; | private final List<Route> routesToInsert; | ||||
private final Context context; | private final Context context; | ||||
//private final NextGenDB nextGenDB; | //private final NextGenDB nextGenDB; | ||||
public BranchInserter(List<Route> routesToInsert,@NonNull Context con) { | public BranchInserter(List<Route> routesToInsert,@NonNull Context con) { | ||||
this.routesToInsert = routesToInsert; | this.routesToInsert = routesToInsert; | ||||
▲ Show 20 Lines • Show All 86 Lines • Show Last 20 Lines |
Public contents are in Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA) or GNU Free Documentation License (at your option) unless otherwise noted. · Contact / Register