package com.papagiannis.tuberun.fetchers;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import android.os.AsyncTask;
import android.util.Log;
import com.papagiannis.tuberun.LinePresentation;
import com.papagiannis.tuberun.LineType;
public class DeparturesTubeFetcher extends DeparturesFetcher {
private static final long serialVersionUID = 3L;
private AtomicBoolean isFirst = new AtomicBoolean(true);
protected int update_counter = 0;
protected LineType line;
protected String station_code, station_nice;
private transient RequestTask task = null;
protected transient XMLDeserialiserTask deserialiserTask;
public DeparturesTubeFetcher(LineType line, String stationcode,
String stationnice) {
this.line = line;
this.station_code = stationcode;
this.station_nice = stationnice;
}
@Override
public void update() {
boolean first = isFirst.compareAndSet(true, false);
if (!first) return;
String request_query = "http://cloud.tfl.gov.uk/TrackerNet/PredictionDetailed/";
if (line==LineType.CIRCLE) request_query+="H";
else request_query+= LinePresentation.getDeparturesRespresentation(line).charAt(0);
request_query+="/"+station_code;
error = "";
task = new RequestTask(new HttpCallback() {
public void onReturn(String s) {
httpCallback(s);
}
});
task.execute(request_query);
}
private void httpCallback(String response) {
if (response == null || response.equals("")) {
error = "The TrackerNet TFL service did not respond to your request (4)";
notifyClients();
}
deserialiserTask = new XMLDeserialiserTask();
deserialiserTask.execute(response);
}
private class XMLDeserialiserTask extends
AsyncTask<String, Integer, ArrayList<HashMap<String, String>>> {
@Override
protected ArrayList<HashMap<String, String>> doInBackground(
String... params) {
ArrayList<HashMap<String, String>> res;
try {
res = parseXMLResponse(params[0]);
} catch (Exception e) {
res = new ArrayList<HashMap<String, String>>();
}
return res;
}
private ArrayList<HashMap<String, String>> parseXMLResponse(
String response) {
ArrayList<HashMap<String, String>> result = new ArrayList<HashMap<String, String>>();
if (response == null || response.equals(""))
return result;
try {
response = response
.substring("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
.length() + 2);
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(new InputSource(new StringReader(
response)));
Element root = dom.getDocumentElement();
NodeList platformsList = root.getElementsByTagName("P");
if (platformsList != null && platformsList.getLength() > 0) {
for (int i = 0; i < platformsList.getLength(); i++) {
Node platform = platformsList.item(i);
String nameString = platform.getNodeName();
if (!nameString.equalsIgnoreCase("P"))
continue;
Node dirNode=platform.getAttributes().getNamedItem("N");
String direction=dirNode.getTextContent();
NodeList trainsList=platform.getChildNodes();
for (HashMap<String,String> train: getTrains(trainsList)) {
train.put("platform",direction);
result.add(train);
}
}
}
} catch (Exception e) {
// This should never happen
Log.w("DeparturesFetcher", e);
}
return result;
}
private ArrayList<HashMap<String, String>> getTrains(NodeList list) {
ArrayList<HashMap<String, String>> result=new ArrayList<HashMap<String,String>>();
if (list==null) return result;
for (int i = 0; i < list.getLength(); i++) {
Node train = list.item(i);
String nodeName = train.getNodeName();
if (!nodeName.equalsIgnoreCase("T"))
continue;
Node timeNode=train.getAttributes().getNamedItem("SecondsTo");
String time=toTimeString(timeNode.getTextContent());
Node locationNode=train.getAttributes().getNamedItem("Location");
String location=locationNode.getTextContent();
Node destinationNode=train.getAttributes().getNamedItem("Destination");
String destination=destinationNode.getTextContent();
HashMap<String,String> m=new HashMap<String, String>();
m.put("time", time);
m.put("position", location);
m.put("destination", destination);
result.add(m);
}
return result;
}
private String toTimeString(String time) {
try {
Integer sec=Integer.parseInt(time);
if (sec<60) return "due";
int min=sec/60;
return min+" min";
}
catch (Exception e) {
return "";
}
}
protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
if (isCancelled())
return;
departures = result;
notifyClients();
isFirst.set(true);
}
}
@Override
public void abort() {
isFirst.set(true);
if (task!=null) task.cancel(true);
if (deserialiserTask!=null) deserialiserTask.cancel(true);
}
}