/[projects]/android/TrainInfoService/src/dk/thoerup/traininfoservice/banedk/DepartureFetcher.java
ViewVC logotype

Annotation of /android/TrainInfoService/src/dk/thoerup/traininfoservice/banedk/DepartureFetcher.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1372 - (hide annotations) (download)
Thu Apr 21 05:51:25 2011 UTC (13 years, 1 month ago) by torben
File size: 17536 byte(s)
Use a enum to select backend
1 torben 305 package dk.thoerup.traininfoservice.banedk;
2    
3 torben 978
4 torben 992 import java.net.URL;
5 torben 994 import java.net.URLEncoder;
6 torben 307 import java.util.Collections;
7 torben 428 import java.util.Map;
8 torben 348 import java.util.logging.Logger;
9 torben 305
10 torben 992 import org.jsoup.nodes.Document;
11     import org.jsoup.nodes.Element;
12     import org.jsoup.select.Elements;
13 torben 305
14 torben 1061 import dk.thoerup.android.traininfo.common.DepartureBean;
15     import dk.thoerup.android.traininfo.common.DepartureEntry;
16     import dk.thoerup.android.traininfo.common.StationBean.StationEntry;
17 torben 468 import dk.thoerup.circuitbreaker.CircuitBreaker;
18     import dk.thoerup.circuitbreaker.CircuitBreakerManager;
19 torben 1366 import dk.thoerup.genericjavautils.HttpUtil;
20 torben 1355 import dk.thoerup.genericjavautils.TimeoutMap;
21 torben 711 import dk.thoerup.traininfoservice.Statistics;
22 torben 1305 import dk.thoerup.traininfoservice.TraininfoSettings;
23 torben 1255 import dk.thoerup.traininfoservice.db.StationDAO;
24 torben 307
25 torben 305 public class DepartureFetcher {
26 torben 348
27 torben 972 enum TrainType{
28     STOG,
29     REGIONAL
30     }
31    
32 torben 1248 enum FetchTrainType {
33     STOG,
34     REGIONAL,
35     BOTH
36     }
37    
38 torben 348 Logger logger = Logger.getLogger(DepartureFetcher.class.getName());
39 torben 387
40 torben 978 Map<String, DepartureBean> cache;
41 torben 387
42 torben 588 StationDAO stationDao = new StationDAO();
43    
44 torben 1303
45     private TraininfoSettings settings;
46 torben 580
47 torben 1303 public DepartureFetcher(TraininfoSettings settings) {
48     this.settings = settings;
49     cache = new TimeoutMap<String,DepartureBean>( settings.getCacheTimeout() );
50 torben 580 }
51    
52    
53 torben 307
54 torben 387
55 torben 1248 public DepartureBean cachedLookupDepartures(int stationID, boolean arrival, FetchTrainType type) throws Exception {
56 torben 980
57 torben 1248 final String key = "" + stationID + ":" + arrival + ":" + type.toString();
58    
59 torben 978 DepartureBean departureBean = cache.get(key);
60 torben 308
61 torben 387
62 torben 978 if (departureBean == null) {
63 torben 1248 departureBean = lookupDepartures(stationID, arrival, type);
64 torben 978 cache.put(key, departureBean);
65 torben 387 } else {
66 torben 711 Statistics.getInstance().incrementDepartureCacheHits();
67 torben 829 logger.info("Departure: Cache hit " + key); //remove before production
68 torben 387 }
69 torben 980 return departureBean;
70 torben 387 }
71    
72    
73 torben 1248 public DepartureBean lookupDepartures(int stationID, boolean arrival, FetchTrainType type) throws Exception {
74 torben 307
75 torben 978 DepartureBean departureBean = new DepartureBean();
76    
77 torben 1060 StationEntry station = stationDao.getById(stationID);
78 torben 307
79 torben 1021 departureBean.stationName = station.getName();
80 torben 1252
81 torben 1248 if (station.getRegional() != null && (type == FetchTrainType.REGIONAL||type == FetchTrainType.BOTH) ) {
82 torben 978 DepartureBean tempBean = lookupDepartures(station.getRegional(), TrainType.REGIONAL, arrival);
83 torben 1063 departureBean.entries.addAll( tempBean.entries );
84 torben 978 departureBean.notifications.addAll(tempBean.notifications);
85 torben 307 }
86    
87 torben 1248 if (station.getStrain() != null && (type == FetchTrainType.STOG||type == FetchTrainType.BOTH)) {
88 torben 978 DepartureBean tempBean = lookupDepartures(station.getStrain(), TrainType.STOG, arrival);
89 torben 1063 departureBean.entries.addAll( tempBean.entries );
90 torben 978 departureBean.notifications.addAll(tempBean.notifications);
91 torben 588 }
92    
93 torben 1063 if (departureBean.entries.size() == 0) {
94 torben 1037 logger.info("No departures found for station " + stationID);
95     }
96    
97 torben 1252 if (type == FetchTrainType.BOTH) { //if we have both S-tog and regional order by departure/arrival time
98     Collections.sort( departureBean.entries );
99     }
100 torben 588
101    
102 torben 978 return departureBean;
103 torben 305 }
104    
105 torben 978 public DepartureBean lookupDepartures(String stationcode, TrainType type, boolean arrival) throws Exception {
106 torben 1372 if ( settings.getBackend() == TraininfoSettings.Backend.Azure) {
107 torben 1034 return lookupDeparturesAzureSite(stationcode, type, arrival);
108     } else {
109 torben 1330 return lookupDeparturesMobileSite(stationcode, type, arrival);
110 torben 580 }
111     }
112    
113 torben 1034 private String getTypeStringAzure(TrainType type) {
114 torben 972 switch (type) {
115     case STOG:
116     return "S-Tog";
117     case REGIONAL:
118     return "Fjerntog";
119     default:
120     return ""; //Can not happen
121     }
122     }
123    
124 torben 1034 private String getTypeStringWww(TrainType type) {
125     switch (type) {
126     case STOG:
127     return "S2";
128     case REGIONAL:
129     return "FJRN";
130     default:
131     return ""; //Can not happen
132     }
133     }
134    
135     public DepartureBean lookupDeparturesAzureSite(String stationcode, TrainType type, boolean arrival) throws Exception {
136 torben 305
137 torben 978 DepartureBean departureBean = new DepartureBean();
138 torben 992
139 torben 970
140 torben 1034 String typeString = getTypeStringAzure(type);
141 torben 970 String arrivalDeparture = (arrival==false) ? "Afgang" : "Ankomst";
142 torben 994
143     stationcode = URLEncoder.encode(stationcode,"ISO-8859-1");
144 torben 970
145 torben 1034 String uri = "http://trafikinfo.bane.dk/Trafikinformation/AfgangAnkomst/" + arrivalDeparture + "/" + stationcode + "/" + typeString + "/UdvidetVisning";
146 torben 994
147 torben 1048 logger.fine("URI: " + uri);
148 torben 1303 JsoupInvocation wrapper = new JsoupInvocation( new URL(uri), settings.getReplyTimeout() );
149 torben 421 CircuitBreaker breaker = CircuitBreakerManager.getManager().getCircuitBreaker("banedk");
150 torben 305
151 torben 992 Document page = (Document) breaker.invoke(wrapper);
152 torben 305
153 torben 829 String tableName = arrival == false ? "afgangtabel" : "ankomsttabel";
154 torben 992 Element table = page.getElementById(tableName);
155 torben 829
156 torben 342 if (table != null) {
157 torben 992 Elements tableRows = table.getElementsByTag("tr");
158 torben 342
159 torben 1188 //boolean tidsstregExists = (table.getElementsByAttributeValue("class", "Tidsstreg").size() > 0);
160     //boolean passedTidsstreg = false;
161 torben 1020
162 torben 992 for (Element currentRow : tableRows) {
163     String rowClass = currentRow.attr("class");
164 torben 1188 /*
165 torben 1020 if (tidsstregExists == true && passedTidsstreg == false) {
166     if (currentRow.getElementsByAttributeValue("class", "Tidsstreg").size() > 0) {
167     passedTidsstreg = true;
168     } else {
169     continue;
170     }
171 torben 1188 }*/
172 torben 1020
173 torben 342 if (rowClass != null && rowClass.toLowerCase().contains("station") ) {
174 torben 1020
175 torben 992 Elements fields = currentRow.getElementsByTag("td");
176 torben 342
177 torben 978 DepartureEntry departure = new DepartureEntry();
178 torben 342
179 torben 992 String time = fields.get(0).text();
180 torben 375 if (time.equals(""))
181     time = "0:00"; //Bane.dk bug work-around
182 torben 342 departure.setTime(time);
183    
184     int updated = extractUpdated( fields.get(1) );
185     departure.setUpdated(updated);
186    
187 torben 992 String trainNumber = fields.get(2).text();
188 torben 972 if (type == TrainType.STOG) //If it is S-train we need to extract the trainNumber
189 torben 1039 trainNumber = trainNumber + " " + extractTrainNumberAzure(fields.get(2));
190 torben 342 departure.setTrainNumber(trainNumber);
191    
192 torben 992 String destination = fields.get(3).text();
193 torben 342 departure.setDestination(destination);
194    
195 torben 992 String origin = fields.get(4).text();
196 torben 342 departure.setOrigin(origin);
197    
198 torben 992 String location = fields.get(5).text();
199 torben 342 departure.setLocation(location);
200    
201 torben 992 String status = fields.get(6).text().trim();
202 torben 342 departure.setStatus(status);
203    
204     String note = extractNote( fields.get(7) );
205     departure.setNote(note);
206    
207 torben 972 departure.setType(typeString);
208 torben 697
209 torben 1063 departureBean.entries.add( departure );
210 torben 342 }
211     }
212 torben 348 } else {
213     logger.warning("No departures found for station=" + stationcode + ", type=" + type);
214 torben 305 }
215 torben 978
216 torben 992 Element notifDiv = page.getElementById("station_planlagte_text");
217 torben 978 if (notifDiv != null) {
218    
219 torben 992 Elements tables = notifDiv.getElementsByTag("table");
220     for (Element tab : tables) {
221 torben 978
222 torben 992 Elements anchors = tab.getElementsByTag("a");
223 torben 978 if (anchors.size() == 2) {
224 torben 992 departureBean.notifications.add( anchors.get(1).text() );
225 torben 978 }
226     }
227    
228     }
229    
230    
231     return departureBean;
232 torben 305 }
233    
234 torben 1330 public DepartureBean lookupDeparturesMobileSite(String stationcode, TrainType traintype, boolean arrival) throws Exception {
235    
236     DepartureBean departureBean = new DepartureBean();
237    
238    
239     String typeString = getTypeStringWww(traintype);
240     String arrivalDeparture = (arrival==false) ? "afgang" : "ankomst";
241    
242     stationcode = URLEncoder.encode(stationcode,"ISO-8859-1");
243    
244     //String uri = "http://trafikinfo.bane.dk/Trafikinformation/AfgangAnkomst/" + arrivalDeparture + "/" + stationcode + "/" + typeString + "/UdvidetVisning";
245     String uri = "http://mobil.bane.dk/mobilStation.asp?artikelID=5332&stat_kode=" + stationcode + "&webprofil=" + typeString +"&beskrivelse=&mode=ankomstafgang&ankomstafgang=" + arrivalDeparture + "&gemstation=&fuldvisning=1";
246     logger.fine("URI: " + uri);
247     JsoupInvocation wrapper = new JsoupInvocation( new URL(uri), settings.getReplyTimeout() );
248     CircuitBreaker breaker = CircuitBreakerManager.getManager().getCircuitBreaker("banedk");
249    
250     Document page = (Document) breaker.invoke(wrapper);
251    
252    
253     Element content = page.getElementsByClass("contentDiv").get(0);
254    
255    
256     if (content != null) {
257     Elements tableRows = content.child(0).children();
258    
259    
260    
261     for (Element currentRow : tableRows) {
262     if (currentRow.tagName().equals("br") ) {
263     break;
264     }
265    
266    
267 torben 1355 String link = currentRow.child(0).attr("href");
268    
269 torben 1335 logger.fine( currentRow.text() );
270 torben 1355 logger.fine("Href: " + link);
271 torben 1330
272    
273     String parts[] = currentRow.text().split(",");
274    
275    
276     DepartureEntry departure = new DepartureEntry();
277 torben 1355
278     //if we do these things upfront, then we are allowed to use continue statement when row contains no more data
279     departure.setType(typeString);
280     departureBean.entries.add( departure );
281 torben 1330
282     /*
283     http://mobil.bane.dk/mobilStation.asp?artikelID=5332&tognummer=111&webprofil=FJRN&mode=rute&strBemaerkning=Afg%E5r+fra+%C5rhus+H+kl%2E07%3A21++&strRefURL=%2FmobilStation%2Easp%3FartikelID%3D5332%26stat%5Fkode%3DAR%26webprofil%3DFJRN%26beskrivelse%3D%25C5rhus%2BH%26mode%3Dankomstafgang%26ankomstafgang%3Dafgang%26gemstation%3D
284     */
285     int offset = 0;
286    
287     String time = parts[offset++];
288     if (time.equals(""))
289     time = "0:00"; //Bane.dk bug work-around
290     departure.setTime(time);
291    
292     int updated = 4; //does not exist on mobile
293     departure.setUpdated(updated);
294    
295 torben 1366 String trainNumber = extractTrainNumberMobile(link);
296 torben 1330 /*if (traintype == TrainType.STOG) //If it is S-train we need to extract the trainNumber
297     trainNumber = trainNumber + " " + extractTrainNumberAzure(fields.get(2));*/
298     departure.setTrainNumber(trainNumber);
299    
300 torben 1334 if (traintype == TrainType.STOG) { //if it is stog the next vield is the "Line" code - this should be used somewhere, but skippint ahead for now
301 torben 1366 String stogLine = parts[offset++].trim();
302     departure.setTrainNumber(stogLine + " " + trainNumber);
303 torben 1333 }
304    
305 torben 1366 String destination = parts[offset++].trim();;
306 torben 1330 departure.setDestination(destination);
307    
308 torben 1332 String origin = "-"; // fields.get(4).text(); does not exist on mobile
309 torben 1330 departure.setOrigin(origin);
310    
311     String location = ""; // fields.get(5).text(); does not exist on mobile
312     departure.setLocation(location);
313 torben 1355
314     if (offset == parts.length) {
315     continue;
316     }
317    
318     if (parts[offset].trim().equalsIgnoreCase("NB!")) {
319     offset++;
320     }
321    
322     if (offset == parts.length) {
323     continue;
324     }
325 torben 1330
326 torben 1366 String status = parts[offset++].trim();; //fields.get(6).text().trim(); - extract from url
327 torben 1330 departure.setStatus(status);
328    
329     String note = ""; //extractNote( fields.get(7) ); - extract from url
330     departure.setNote(note);
331    
332     }
333     } else {
334     logger.warning("No departures found for station=" + stationcode + ", type=" + traintype);
335     }
336    
337     return departureBean;
338     }
339 torben 1038
340    
341 torben 1330
342 torben 1040 public static String cleanText(String input) {
343     //apparently JSoup translates &nbsp; characters on www.bane.dk to 0xA0
344 torben 1038 return input.replace((char) 0xA0, (char)0x20).trim();
345     }
346    
347 torben 1330
348     // old www site is not available any more
349     @Deprecated
350 torben 1034 public DepartureBean lookupDeparturesWwwSite(String stationcode, TrainType trainType, boolean arrival) throws Exception {
351 torben 580
352 torben 1034 DepartureBean departureBean = new DepartureBean();
353 torben 580
354 torben 1034 String type = getTypeStringWww(trainType);
355    
356 torben 1045 stationcode = URLEncoder.encode(stationcode, "ISO-8859-1");
357    
358 torben 1034
359     String uri = "http://www.bane.dk/visStation.asp?ArtikelID=4275&W=" + type + "&S=" + stationcode;
360 torben 1048 logger.fine("URI:" + uri);
361    
362 torben 1047
363 torben 1303 JsoupInvocation wrapper = new JsoupInvocation( new URL(uri), settings.getReplyTimeout() );
364 torben 580 CircuitBreaker breaker = CircuitBreakerManager.getManager().getCircuitBreaker("banedk");
365    
366 torben 1034 Element page = (Element) breaker.invoke(wrapper);
367 torben 580
368 torben 1034 String tableName = arrival == false ? "afgangtabel" : "ankomsttabel";
369     Element table = page.getElementById(tableName);
370 torben 580
371 torben 1046
372    
373 torben 1034 if (table != null) {
374     Elements tableRows = table.getElementsByTag("tr");
375 torben 580
376 torben 1188 //boolean passedTidsstreg = false;
377     //boolean tidsstregExists = (table.getElementsByAttributeValue("class", "Tidsstreg").size() > 0);
378 torben 1046
379 torben 1034 for (Element currentRow : tableRows) {
380     String rowClass = currentRow.attr("class");
381 torben 1188 /*
382 torben 1046 if (tidsstregExists == true && passedTidsstreg == false) {
383     if (currentRow.getElementsByAttributeValue("class", "Tidsstreg").size() > 0) {
384     passedTidsstreg = true;
385     } else {
386     continue;
387     }
388 torben 1188 }*/
389 torben 1046
390    
391 torben 1034 if (rowClass != null && rowClass.toLowerCase().contains("station") ) {
392     Elements fields = currentRow.getElementsByTag("td");
393    
394     DepartureEntry departure = new DepartureEntry();
395    
396    
397    
398 torben 1038 String time = cleanText( fields.get(0).getAllElements().get(2).text() );
399 torben 1034 if (time.equals(""))
400     time = "0:00"; //Bane.dk bug work-around
401     departure.setTime(time);
402    
403     int updated = extractUpdated( fields.get(1) );
404     departure.setUpdated(updated);
405    
406 torben 1038 String trainNumber = cleanText( fields.get(2).text() );
407 torben 1034 if (type.equalsIgnoreCase("S2")) //If it is S-train we need to extract the trainNumber
408 torben 1039 trainNumber = trainNumber + " " + extractTrainNumberWww(fields.get(2));
409 torben 1034 departure.setTrainNumber(trainNumber);
410    
411 torben 1038 String destination = cleanText( fields.get(3).text() );
412 torben 1034 departure.setDestination(destination);
413    
414 torben 1038 String origin = cleanText( fields.get(4).text() );
415 torben 1034 departure.setOrigin(origin);
416    
417 torben 1038 String location = cleanText( fields.get(5).text() );
418 torben 1034 departure.setLocation(location);
419    
420 torben 1038 String status = cleanText( fields.get(6).text() );
421 torben 1034 departure.setStatus(status);
422    
423 torben 1038 String note = cleanText( extractNote( fields.get(7) ) );
424 torben 1034 departure.setNote(note);
425    
426     departure.setType(type);
427    
428 torben 1063 departureBean.entries.add(departure);
429 torben 1034
430    
431 torben 580 }
432     }
433     } else {
434     logger.warning("No departures found for station=" + stationcode + ", type=" + type);
435     }
436    
437 torben 591
438 torben 1034 return departureBean;
439     }
440    
441 torben 580
442 torben 992 private int extractUpdated(Element updatedTd) { //extract the digit (in this case: 4) from "media/trafikinfo/opdater4.gif"
443 torben 305 int updated = -1;
444    
445 torben 992 Elements updatedImgs = updatedTd.getElementsByTag("img");
446     String updatedStr = updatedImgs.get(0).attr("src");
447 torben 305
448     if (updatedStr != null) {
449     for (int i=0; i<updatedStr.length(); i++) {
450     char c = updatedStr.charAt(i);
451     if ( Character.isDigit(c)) {
452     updated = Character.digit(c, 10);
453     break;
454     }
455     }
456     }
457     return updated;
458     }
459    
460 torben 992 private String extractNote(Element noteTd) {
461     String note = noteTd.text().trim();
462 torben 313
463 torben 992
464     Elements elems = noteTd.getElementsByClass("bemtype");
465 torben 313 if (elems.size() > 0 && note.charAt(note.length()-1) == 'i')
466     note = note.substring(0,note.length() -1 );
467    
468 torben 1038 return note.trim();
469 torben 313 }
470    
471 torben 1039 private String extractTrainNumberAzure(Element trainTd) {
472 torben 992 Element anchorElement = trainTd.getElementsByTag("a").get(0);
473     String href = anchorElement.attr("href");
474 torben 349
475 torben 973 int pos = href.lastIndexOf('/');
476     String number = href.substring(pos+1);
477 torben 970
478 torben 349 return number;
479     }
480    
481 torben 1366 private String extractTrainNumberMobile(String link) {
482     Map<String,String> elements = HttpUtil.decodeParams(link);
483    
484     return elements.get("tognummer");
485     }
486    
487 torben 1039 private String extractTrainNumberWww(Element trainTd) {
488     String number = "";
489     Element anchorElement = trainTd.getElementsByTag("a").get(0);
490     String href = anchorElement.attr("href");
491 torben 1366
492     String argstring = href.split("?")[1];
493     Map<String,String> elements = HttpUtil.decodeParams(argstring);
494     number = elements.get("TogNr");
495 torben 1039
496 torben 1366
497     /*String argstring = href.substring( href.indexOf('?') + 1);
498 torben 1039 String args[] = argstring.split("&");
499     for (String arg : args) {
500     String pair[] = arg.split("="); // Key=pair[0], Value=pair[1]
501    
502     if (pair[0].equalsIgnoreCase("TogNr"))
503     number = pair[1];
504 torben 1366 }*/
505    
506 torben 1039
507     return number;
508     }
509    
510    
511 torben 305 //test
512 torben 580 /*
513 torben 451 public static void main(String args[]) throws Exception {
514 torben 305 DepartureFetcher f = new DepartureFetcher();
515 torben 307 List<DepartureBean> deps = f.lookupDepartures("AR", "FJRN");
516 torben 305 for(DepartureBean d : deps) {
517     System.out.println( d.getTime() + ";" + d.getUpdated() + ";" + d.getTrainNumber() + ";" +
518     d.getDestination() + ";" + d.getOrigin() + ";" + d.getLocation() + ";" + d.getStatus() + ";" + d.getNote() );
519     }
520    
521     System.out.println("--------------------------");
522 torben 580 }*/
523 torben 305 }

  ViewVC Help
Powered by ViewVC 1.1.20