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

Contents of /android/TrainInfoService/src/dk/thoerup/traininfoservice/banedk/TimetableFetcher.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1060 - (show annotations) (download)
Thu Sep 16 13:32:10 2010 UTC (13 years, 8 months ago) by torben
File size: 7166 byte(s)
Experimental: use Simple (simple.sourceforge.net) for XML serialization
1 package dk.thoerup.traininfoservice.banedk;
2
3
4
5 import java.net.URL;
6 import java.sql.SQLException;
7 import java.util.Map;
8 import java.util.logging.Level;
9 import java.util.logging.Logger;
10
11 import org.jsoup.nodes.Document;
12 import org.jsoup.nodes.Element;
13 import org.jsoup.select.Elements;
14
15 import dk.thoerup.circuitbreaker.CircuitBreaker;
16 import dk.thoerup.circuitbreaker.CircuitBreakerManager;
17 import dk.thoerup.traininfoservice.StationDAO;
18 import dk.thoerup.traininfoservice.Statistics;
19
20 public class TimetableFetcher {
21
22
23 Map<String, TimetableBean> cache;
24 Map<String, Integer> stationCache;
25
26 StationDAO stationDao = new StationDAO();
27
28
29 Logger logger = Logger.getLogger(TimetableFetcher.class.getName());
30
31 private boolean useAzureSite;
32 private int replyTimeout;
33
34 public TimetableFetcher(boolean azureSite, int cacheTimeout, int replyTimeout) {
35 useAzureSite = azureSite;
36 this.replyTimeout = replyTimeout;
37
38 cache = new TimeoutMap<String,TimetableBean>(cacheTimeout);
39 stationCache = new TimeoutMap<String,Integer>( 3*60*60*1000 );
40 }
41
42
43 TimetableBean cachedLookupTimetable(String trainID, String type) throws Exception {
44 String key = trainID+type;
45 TimetableBean list = cache.get(key);
46
47 if (list == null) {
48 list = lookupTimetable(trainID,type);
49 cache.put(key, list);
50 } else {
51 Statistics.getInstance().incrementTimetableCacheHits();
52 logger.info("Timetable: Cache hit " + trainID);
53 }
54 return list;
55 }
56
57 TimetableBean lookupTimetable(String trainID, String type) throws Exception {
58 if (useAzureSite == true ){
59 return lookupTimetableAzureSite(trainID, type);
60
61 } else {
62 return lookupTimetableWwwSite(trainID, type);
63 }
64 }
65
66 int getStationId(String name) {
67 Integer id = stationCache.get(name);
68
69 if (id == null) {
70 try {
71 id = stationDao.getIdByName(name);
72 stationCache.put(name, id);
73 } catch (SQLException e) {
74 logger.log(Level.SEVERE, "getStationId failed", e);
75 id = -1;
76 }
77 }
78
79 return id;
80 }
81
82 TimetableBean lookupTimetableAzureSite(String trainID, String type) throws Exception {
83 TimetableBean timetableBean = new TimetableBean();
84
85
86 String url = "http://trafikinfo.bane.dk/TrafikInformation/Ruteplan/" + trainID;
87 logger.fine("URL:" + url);
88
89 JsoupInvocation wrapper = new JsoupInvocation( new URL(url) , replyTimeout);
90 CircuitBreaker breaker = CircuitBreakerManager.getManager().getCircuitBreaker("banedk");
91
92 Document doc = (Document) breaker.invoke(wrapper);
93
94
95 boolean currentStation = false;
96 boolean currentStationSaved = false;
97
98 Elements tables = doc.getElementsByClass("Rute");
99
100 if (tables.size() == 1) {
101 Element timetable = tables.get(0);
102 Elements rows = timetable.getElementsByTag("tr");
103
104 for (int i=0; i<rows.size(); i++) {
105 if (i==0) //First row is column headers
106 continue;
107
108
109 Element row = rows.get(i);
110 Elements fields = row.getElementsByTag("td");
111
112
113 if (currentStationSaved == false && fields.get(0).attr("class").equalsIgnoreCase("Tidsstreg")) {
114 currentStation = true;
115 continue;
116 }
117
118 TimetableEntry entry = new TimetableEntry();
119
120 String station = fields.get(0).text() ;
121 if (station.equals("København"))
122 station = "København H"; //correct inconsistency in naming
123
124 entry.setStation( station );
125 entry.setArrival( fields.get(1).text() );
126 entry.setDeparture( fields.get(2).text() );
127
128 boolean cancelled = fields.get(3).text().equalsIgnoreCase("aflyst");
129 entry.setCancelled(cancelled);
130
131 if (currentStation == true && currentStationSaved == false ) {
132 entry.setCurrent(currentStation);
133 currentStationSaved = true;
134 }
135
136 entry.setStationId( getStationId( station ));
137
138 timetableBean.entries.add(entry);
139 }
140
141 //TODO: There is an off-by-one error in this cancelled parser thingie
142 final String cancelledString = "Aflyst";
143 for (int i=0;i<timetableBean.entries.size(); i++) { //handle cancelled labels
144 final int lastIdx = (timetableBean.entries.size() - 1);
145
146 TimetableEntry current = timetableBean.entries.get(i);
147 if (current.isCancelled()) {
148 if (i == 0) {
149 current.setDeparture(cancelledString);
150 } else if (i == lastIdx) {
151 current.setArrival(cancelledString);
152 } else if (i>0 && i<lastIdx) {
153 TimetableEntry next = timetableBean.entries.get(i+1);
154 TimetableEntry prev = timetableBean.entries.get(i-1);
155
156 if (next.isCancelled())
157 current.setDeparture(cancelledString);
158 if (prev.isCancelled())
159 current.setArrival(cancelledString);
160 }
161 }
162 }
163
164 } else {
165 logger.warning("No time table found, trainID=" + trainID + " type=" + type);
166 }
167
168
169 return timetableBean;
170 }
171
172 TimetableBean lookupTimetableWwwSite(String trainID, String type) throws Exception {
173 TimetableBean timetableBean = new TimetableBean();
174
175 String url = "http://www.bane.dk/visRute.asp?W=" + type + "&TogNr=" + trainID + "&artikelId=4276";
176 logger.fine("URL:" + url);
177
178
179 JsoupInvocation wrapper = new JsoupInvocation( new URL(url) , replyTimeout);
180 CircuitBreaker breaker = CircuitBreakerManager.getManager().getCircuitBreaker("banedk");
181
182 Document doc = (Document) breaker.invoke(wrapper);
183
184
185 boolean currentStation = false;
186 boolean currentStationSaved = false;
187
188 Elements tables = doc.getElementsByClass("Rute");
189
190 if (tables.size() == 1) {
191 Element timetable = tables.get(0);
192 Elements rows = timetable.getElementsByTag("tr");
193
194 for (int i=0; i<rows.size(); i++) {
195 if (i==0) //First row is column headers
196 continue;
197
198
199 Element row = rows.get(i);
200 Elements fields = row.getElementsByTag("td");
201
202
203 if (currentStationSaved == false && fields.get(0).attr("class").equalsIgnoreCase("Tidsstreg")) {
204 currentStation = true;
205 continue;
206 }
207
208 TimetableEntry entry = new TimetableEntry();
209
210 String station = DepartureFetcher.cleanText( fields.get(0).text() ) ;
211 if (station.equals("København"))
212 station = "København H"; //correct inconsistency in naming
213
214 String arrival = DepartureFetcher.cleanText( fields.get(1).text() );
215 String departure = DepartureFetcher.cleanText( fields.get(2).text() );
216
217 entry.setStation( station );
218 entry.setArrival( arrival );
219 entry.setDeparture( departure );
220
221
222 if (currentStation == true && currentStationSaved == false ) {
223 entry.setCurrent(currentStation);
224 currentStationSaved = true;
225 }
226
227 entry.setStationId( getStationId( station ));
228
229 timetableBean.entries.add(entry);
230 }
231
232 } else {
233 logger.warning("No time table found, trainID=" + trainID + " type=" + type);
234 }
235
236
237 return timetableBean;
238 }
239
240 }

  ViewVC Help
Powered by ViewVC 1.1.20