Java tutorial
/** * Copyright 2014 Carl-Philipp Harmant * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package fr.cph.chicago.task; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map.Entry; import org.apache.commons.collections4.MultiMap; import org.apache.commons.collections4.map.MultiValueMap; import android.os.AsyncTask; import android.util.Log; import android.util.SparseArray; import fr.cph.chicago.connection.CtaConnect; import fr.cph.chicago.connection.CtaRequestType; import fr.cph.chicago.connection.DivvyConnect; import fr.cph.chicago.data.DataHolder; import fr.cph.chicago.data.Preferences; import fr.cph.chicago.data.TrainData; import fr.cph.chicago.entity.BikeStation; import fr.cph.chicago.entity.BusArrival; import fr.cph.chicago.entity.Eta; import fr.cph.chicago.entity.Station; import fr.cph.chicago.entity.TrainArrival; import fr.cph.chicago.entity.enumeration.TrainDirection; import fr.cph.chicago.entity.enumeration.TrainLine; import fr.cph.chicago.exception.ConnectException; import fr.cph.chicago.exception.ParserException; import fr.cph.chicago.exception.TrackerException; import fr.cph.chicago.json.Json; import fr.cph.chicago.util.Util; import fr.cph.chicago.xml.Xml; /** * CTA connect task * * @author Carl-Philipp Harmant * @version 1 */ public class GlobalConnectTask extends AsyncTask<Void, Void, Boolean> { /** Tag **/ private static final String TAG = "GlobalConnectTask"; /** Instance of the class where the we will callback **/ private Object mInstance; /** The class **/ private Class<?> mClasse; /** Request type **/ private CtaRequestType mRequestType, mRequestType2; /** The params of the requests **/ private MultiMap<String, String> mParams, mParams2; /** The XML parser **/ private Xml mXml; /** The Json parser **/ private Json mJson; /** List of train arrivals **/ private SparseArray<TrainArrival> mTrainArrivals; /** Train data **/ private TrainData mData; /** Train exception **/ private TrackerException mTrackerTrainException; /** Bus exception **/ private TrackerException mTrackerBusException; /** Bike exception **/ private TrackerException mTrackerBikeException; /** Bus arrivals **/ private List<BusArrival> mBusArrivals; /** Bike stations **/ private List<BikeStation> mBikeStations; /** Error train */ private boolean mTrainBoolean; /** Error bus **/ private boolean mBusBoolean; /** Error bike **/ private boolean mBikeBoolean; /** Load trains or not **/ private boolean mLoadTrains; /** Load buses or not **/ private boolean mLoadBuses; /** Load bikes or not **/ private boolean mLoadBikes; /** **/ private boolean mNetworkAvailable; /** * Constructor * * @param instance * Instance of the object * @param classe * The class * @param requestType * the request type * @param params * the params * @param requestType2 * the request type * @param params2 * the params * @throws ParserException * the parser exception */ public GlobalConnectTask(final Object instance, final Class<?> classe, final CtaRequestType requestType, final MultiMap<String, String> params, final CtaRequestType requestType2, final MultiMap<String, String> params2, boolean loadTrains, boolean loadBuses, boolean loadBikes) throws ParserException { this.mInstance = instance; this.mClasse = classe; this.mRequestType = requestType; this.mParams = params; this.mData = DataHolder.getInstance().getTrainData(); this.mRequestType2 = requestType2; this.mParams2 = params2; this.mTrainArrivals = new SparseArray<TrainArrival>(); this.mBusArrivals = new ArrayList<BusArrival>(); this.mBikeStations = new ArrayList<BikeStation>(); this.mXml = new Xml(); this.mJson = new Json(); this.mLoadTrains = loadTrains; this.mLoadBuses = loadBuses; this.mLoadBikes = loadBikes; } @Override protected final Boolean doInBackground(final Void... connects) { mTrainBoolean = true; mBusBoolean = true; mBikeBoolean = true; mNetworkAvailable = Util.isNetworkAvailable(); if (mNetworkAvailable) { CtaConnect ctaConnect = CtaConnect.getInstance(); DivvyConnect divvyConnect = DivvyConnect.getInstance(); if (mLoadTrains) { try { for (Entry<String, Object> entry : mParams.entrySet()) { String key = entry.getKey(); if (key.equals("mapid")) { Object value = entry.getValue(); if (value instanceof String) { String xmlResult = ctaConnect.connect(mRequestType, mParams); this.mTrainArrivals = mXml.parseArrivals(xmlResult, mData); } else if (value instanceof List) { @SuppressWarnings("unchecked") List<String> list = (List<String>) value; if (list.size() < 5) { String xmlResult = ctaConnect.connect(mRequestType, mParams); this.mTrainArrivals = mXml.parseArrivals(xmlResult, mData); } else { int size = list.size(); SparseArray<TrainArrival> tempArrivals = new SparseArray<TrainArrival>(); int start = 0; int end = 4; while (end < size + 1) { List<String> subList = list.subList(start, end); MultiMap<String, String> paramsTemp = new MultiValueMap<String, String>(); for (String sub : subList) { paramsTemp.put(key, sub); } String xmlResult = ctaConnect.connect(mRequestType, paramsTemp); SparseArray<TrainArrival> temp = mXml.parseArrivals(xmlResult, mData); for (int j = 0; j < temp.size(); j++) { tempArrivals.put(temp.keyAt(j), temp.valueAt(j)); } start = end; if (end + 3 >= size - 1 && end != size) { end = size; } else { end = end + 3; } } this.mTrainArrivals = tempArrivals; } } } } // Apply filters int index = 0; while (index < mTrainArrivals.size()) { TrainArrival arri = mTrainArrivals.valueAt(index++); List<Eta> etas = arri.getEtas(); // Sort Eta by arriving time Collections.sort(etas); // Copy data into new list to be able to avoid looping on a list that we want to // modify List<Eta> etas2 = new ArrayList<Eta>(); etas2.addAll(etas); int j = 0; Eta eta = null; Station station = null; TrainLine line = null; TrainDirection direction = null; for (int i = 0; i < etas2.size(); i++) { eta = etas2.get(i); station = eta.getStation(); line = eta.getRouteName(); direction = eta.getStop().getDirection(); boolean toRemove = Preferences.getTrainFilter(station.getId(), line, direction); if (!toRemove) { etas.remove(i - j++); } } } } catch (ConnectException e) { mTrainBoolean = false; this.mTrackerTrainException = e; } catch (ParserException e) { mTrainBoolean = false; this.mTrackerTrainException = e; } } if (mLoadBuses) { try { List<String> rts = new ArrayList<String>(); List<String> stpids = new ArrayList<String>(); for (Entry<String, Object> entry : mParams2.entrySet()) { String key = entry.getKey(); StringBuilder str = new StringBuilder(); int i = 0; @SuppressWarnings("unchecked") List<String> values = (ArrayList<String>) entry.getValue(); for (String v : values) { str.append(v + ","); if (i == 9 || i == values.size() - 1) { if (key.equals("rt")) { rts.add(str.toString()); } else if (key.equals("stpid")) { stpids.add(str.toString()); } str = new StringBuilder(); i = -1; } i++; } } for (int i = 0; i < rts.size(); i++) { MultiMap<String, String> para = new MultiValueMap<String, String>(); para.put("rt", rts.get(i)); para.put("stpid", stpids.get(i)); String xmlResult = ctaConnect.connect(mRequestType2, para); this.mBusArrivals.addAll(mXml.parseBusArrivals(xmlResult)); } } catch (ConnectException e) { mBusBoolean = false; this.mTrackerBusException = e; } catch (ParserException e) { mBusBoolean = false; this.mTrackerBusException = e; } } if (mLoadBikes) { try { String bikeContent = divvyConnect.connect(); this.mBikeStations = mJson.parseStations(bikeContent); Collections.sort(this.mBikeStations, Util.BIKE_COMPARATOR_NAME); } catch (ParserException e) { mBikeBoolean = false; this.mTrackerBikeException = e; } catch (ConnectException e) { mBikeBoolean = false; this.mTrackerBikeException = e; } finally { if (!(mBusBoolean && mTrainBoolean)) { if (mParams2.size() == 0 && mBusBoolean) { mBusBoolean = false; } if (mParams.size() == 0 && mTrainBoolean) { mTrainBoolean = false; } } } } return mTrainBoolean || mBusBoolean || mBikeBoolean; } else { return mNetworkAvailable; } } @Override protected final void onProgressUpdate(final Void... progress) { } @Override protected final void onPostExecute(final Boolean success) { try { if (success) { mClasse.getMethod("reloadData", SparseArray.class, List.class, List.class, Boolean.class, Boolean.class, Boolean.class, Boolean.class).invoke(mInstance, this.mTrainArrivals, this.mBusArrivals, this.mBikeStations, this.mTrainBoolean, this.mBusBoolean, this.mBikeBoolean, this.mNetworkAvailable); } else if (!mNetworkAvailable) { mClasse.getMethod("reloadData", SparseArray.class, List.class, List.class, Boolean.class, Boolean.class, Boolean.class, Boolean.class).invoke(mInstance, this.mTrainArrivals, this.mBusArrivals, this.mBikeStations, false, false, false, this.mNetworkAvailable); } else { TrackerException ex = mTrackerBusException == null ? (mTrackerBikeException == null ? mTrackerTrainException : mTrackerBikeException) : mTrackerBusException; if (ex != null) { // because both can be null Log.e(TAG, ex.getMessage(), ex); } mClasse.getMethod("displayError", TrackerException.class).invoke(mInstance, ex); } } catch (Exception e) { Log.e(TAG, e.getMessage(), e); } super.onPostExecute(success); } }