package com.papagiannis.tuberun.fetchers; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; 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 DeparturesDLRFetcher extends DeparturesTubeFetcher { private static final long serialVersionUID = 4L; public static final String none_msg = ""; private AtomicBoolean isFirst = new AtomicBoolean(true); protected int update_counter = 0; protected String line, station_code, station_nice; protected transient RequestTask task; protected transient XMLDeserialiserTask deserialiserTask; public DeparturesDLRFetcher(LineType line, String stationcode, String stationnice) { super(line, stationcode, stationnice); this.line = LinePresentation.getDeparturesRespresentation(line); station_code = stationcode; station_nice = stationnice; } @Override public void update() { boolean first = isFirst.compareAndSet(true, false); if (!first) return; // only one at a time departures.clear(); error = ""; String request_query = "http://www.dlrlondon.co.uk/xml/mobile/" + station_code + ".xml"; 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 DLR TFL server 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>>(); int platform_number = 0; 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 ttBoxList = root.getChildNodes(); if (ttBoxList != null && ttBoxList.getLength() > 0) { for (int i = 0; i < ttBoxList.getLength(); i++) { Node ttBox = ttBoxList.item(i); String nameString = ttBox.getNodeName(); if (nameString.equalsIgnoreCase("#text")) continue; NodeList ttBoxPlatformList = ttBox.getChildNodes(); if (ttBoxPlatformList.getLength() < 2) continue; Node middlePlaform = null; for (int k = 0; k < ttBoxPlatformList.getLength(); k++) { Node child = ttBoxPlatformList.item(k); nameString = child.getNodeName(); if (nameString.equalsIgnoreCase("#text")) continue; NamedNodeMap attrs = child.getAttributes(); if (attrs == null) continue; Node id_node = attrs.getNamedItem("id"); String id = id_node.getNodeValue(); if (id.equalsIgnoreCase("platformmiddle")) { middlePlaform = child; break; } } nameString = middlePlaform.getNodeName(); if (nameString.equalsIgnoreCase("#text")) continue; NodeList divList = middlePlaform.getChildNodes(); HashMap<String, String> train = new HashMap<String, String>(); for (int j = 0; j < divList.getLength(); j++) { Node div = divList.item(j); nameString = div.getNodeName(); if (nameString.equalsIgnoreCase("#text")) continue; NamedNodeMap att = div.getAttributes(); Node id = att.getNamedItem("id"); nameString = id.getNodeName(); if (nameString.equalsIgnoreCase("#text")) continue; String id_value = id.getNodeValue(); if (id_value.equalsIgnoreCase("line1")) { String data = div.getTextContent(); train = decodeLine(data); if (train==null) continue; platform_number++; train.put("platform", "Platform " + platform_number); result.add(train); } else if (id_value.equalsIgnoreCase("line23")) { String data = div.getTextContent(); if (data == null) continue; String[] tokens = data.split("\n\n"); for (String token : tokens) { train = decodeLine(token); if (train==null) continue; train.put("platform", "Platform " + platform_number); result.add(train); } } } } } } catch (Exception e) { // This should never happen Log.w("DLR Fetcher", e); } return result; } private HashMap<String, String> decodeLine(String line) { line = cleanHTML(line); return getInfo(line); } private String cleanHTML(String s) { String res = s.replace("<p>", " "); res = res.replace("</p>", " "); res = res.replace("\n", " "); res = res.replace("\t", " "); res = res.replace("\r", " "); res = res.replace("<br>", " "); res = res.replace("<br/>", " "); res = res.replace(" ", " "); res = res.trim(); String[] tokens = res.split(" "); res = ""; for (String ss : tokens) { if (ss != null && !ss.equals("")) res += ss + " "; } return res; } private HashMap<String, String> getInfo(String tr1) { HashMap<String, String> train1 = new HashMap<String, String>(); String dec = "(1|2|3|4|5|6|7|8|9|0)"; Pattern pat = Pattern.compile("[1-3]( )((([^0-9])+[0-9]+.*)| *)"); Matcher m = pat.matcher(tr1); String dest = ""; String time = ""; String where = ""; if (m.find() && m.start() != -1) { Boolean first_nums = false; Boolean seond_nums = false; for (int j = 0; j < tr1.length(); j++) { char c = tr1.charAt(j); if (first_nums == false) { if (!dec.contains("" + c)) continue; else first_nums = true; } else if (seond_nums == false) { if (!dec.contains("" + c)) dest = dest + c; else { time = time + c; seond_nums = true; } } else { if (!dec.contains("" + c)) break; else time = time + c; } } dest = dest.trim(); if (time != "") time = time + " min"; where = none_msg; dest = toCamelCase(dest); String destn = ""; Boolean white = true; for (int j = 0; j < dest.length(); j++) { char c = tr1.charAt(j); if (white) { white = false; destn += String.valueOf(c).toUpperCase(Locale.ENGLISH); } else { if (c == ' ') white = true; destn += c; } } if (destn.length() > 3) { train1.put("time", time); train1.put("destination", dest); train1.put("position", where); return train1; } else return null; } else { return null; } } private String toCamelCase(String s) { boolean previous_whitespace = true; String result = ""; for (int i = 0; i < s.length(); i++) { String next = s.substring(i, i + 1); if (previous_whitespace) { result += next.toUpperCase(Locale.ENGLISH); } else { result += next.toLowerCase(Locale.ENGLISH); } previous_whitespace=next.equals(" "); } return result; } 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); } }