();
-
- final Matcher mConCoarse = P_CONNECTIONS_COARSE.matcher(page);
- while (mConCoarse.find())
- {
- final Matcher mConFine = P_CONNECTIONS_FINE.matcher(mConCoarse.group(1));
- if (mConFine.matches())
- {
- final String link = API_BASE + ParserUtils.resolveEntities(mConFine.group(3));
-
- if (mConFine.group(6) == null)
- {
- Date date;
- if (mConFine.group(1) != null)
- date = parseDate(mConFine.group(1), mConFine.group(2), new SimpleDateFormat("yyyy").format(currentDate));
- else
- date = currentDate;
- Date departureTime = ParserUtils.joinDateTime(date, ParserUtils.parseTime(mConFine.group(4)));
- if (!connections.isEmpty())
- {
- final long diff = ParserUtils.timeDiff(departureTime, connections.get(connections.size() - 1).departureTime);
- if (diff > PARSER_DAY_ROLLOVER_THRESHOLD_MS)
- departureTime = ParserUtils.addDays(departureTime, -1);
- else if (diff < -PARSER_DAY_ROLLOVER_THRESHOLD_MS)
- departureTime = ParserUtils.addDays(departureTime, 1);
- }
- Date arrivalTime = ParserUtils.joinDateTime(date, ParserUtils.parseTime(mConFine.group(5)));
- if (departureTime.after(arrivalTime))
- arrivalTime = ParserUtils.addDays(arrivalTime, 1);
- final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, null, null, 0,
- from.name, 0, to.name, null);
- connections.add(connection);
- }
- else
- {
- final int min = Integer.parseInt(mConFine.group(6)) * 60 + Integer.parseInt(mConFine.group(7));
- final Calendar calendar = new GregorianCalendar();
- final Date departureTime = calendar.getTime();
- calendar.add(Calendar.MINUTE, min);
- final Date arrivalTime = calendar.getTime();
- final Connection connection = new Connection(ParserUtils.extractId(link), link, departureTime, arrivalTime, null, null, 0,
- from.name, 0, to.name, null);
- connections.add(connection);
- }
- }
- else
- {
- throw new IllegalArgumentException("cannot parse '" + mConCoarse.group(1) + "' on " + uri);
- }
- }
-
- return new QueryConnectionsResult(uri, from, via, to, linkEarlier, linkLater, connections);
- }
- else
- {
- throw new IOException(page.toString());
- }
- }
-
- private static final Pattern P_CONNECTION_DETAILS_HEAD = Pattern.compile(".*?Detailansicht.*?" //
- + "Datum:[\\xa0\\s]+\\w{2}\\.,\\s(\\d+)\\.\\s(\\w{3,4})\\.[\\xa0\\s]+(\\d{4}).*?", Pattern.DOTALL);
- private static final Pattern P_CONNECTION_DETAILS_COARSE = Pattern.compile("" //
- + "\r\\x0a(.+?)
.*?" //
- + "\r\\x0a(.+?)
.*?" //
- + "\r\\x0a(.+?)
", Pattern.DOTALL);
- static final Pattern P_CONNECTION_DETAILS_FINE = Pattern.compile("(?:" //
- + "ab (\\d{1,2}:\\d{2})\\s(.*?)\\s*<.*?" // departureTime, departure
- + "(?: .*?)?" // product
- + " | \\s*(.*?)\\s* Richtung\\s*(.*?)\\s* | .*?" // line, destination
- + "an (\\d{1,2}:\\d{2})\\s(.*?)\\s*<" // arrivalTime, arrival
- + "|" //
- + " | ab (.*?)\\s*<.*?" // departure
- + "Fußweg[\\xa0\\s]+\\(ca\\.[\\xa0\\s]+(\\d+)[\\xa0\\s]+Minute.*?" // min
- + " | an (.*?)\\s*<" // arrival
- + "|" //
- + ".*? " //
- + ").*?", Pattern.DOTALL);
- private static final Pattern P_CONNECTION_DETAILS_ERRORS = Pattern.compile("(session has expired)", Pattern.CASE_INSENSITIVE);
-
- @Override
- public GetConnectionDetailsResult getConnectionDetails(final String uri) throws IOException
- {
- final CharSequence page = ParserUtils.scrape(uri);
-
- final Matcher mHead = P_CONNECTION_DETAILS_HEAD.matcher(page);
- if (mHead.matches())
- {
- final Date currentDate = parseDate(mHead.group(1), mHead.group(2), mHead.group(3));
- final List parts = new ArrayList(4);
-
- Date lastTime = currentDate;
-
- Date firstDepartureTime = null;
- String firstDeparture = null;
- Date lastArrivalTime = null;
- String lastArrival = null;
- String oldZebra = null;
-
- final Matcher mDetCoarse = P_CONNECTION_DETAILS_COARSE.matcher(page);
- while (mDetCoarse.find())
- {
- final String zebra = mDetCoarse.group(1);
- if (oldZebra != null && zebra.equals(oldZebra))
- throw new IllegalArgumentException("missed row? last:" + zebra);
- else
- oldZebra = zebra;
-
- final String set = mDetCoarse.group(2) + mDetCoarse.group(3) + mDetCoarse.group(4);
- final Matcher mDetFine = P_CONNECTION_DETAILS_FINE.matcher(set);
- if (mDetFine.matches())
- {
- if (mDetFine.group(1) != null)
- {
- final Date departureTime = upTime(lastTime, ParserUtils.joinDateTime(currentDate, ParserUtils.parseTime(mDetFine.group(1))));
-
- final String departure = ParserUtils.resolveEntities(mDetFine.group(2));
- if (departure != null && firstDeparture == null)
- firstDeparture = departure;
-
- final String product = ParserUtils.resolveEntities(mDetFine.group(3));
-
- final String line = ParserUtils.resolveEntities(mDetFine.group(4));
-
- final String destination = ParserUtils.resolveEntities(mDetFine.group(5));
-
- final Date arrivalTime = upTime(lastTime, ParserUtils.joinDateTime(currentDate, ParserUtils.parseTime(mDetFine.group(6))));
-
- final String arrival = ParserUtils.resolveEntities(mDetFine.group(7));
-
- final String normalizedLine = normalizeLine(product, line);
-
- parts.add(new Connection.Trip(normalizedLine, LINES.get(normalizedLine), 0, destination, departureTime, null, 0, departure,
- arrivalTime, null, 0, arrival));
-
- if (firstDepartureTime == null)
- firstDepartureTime = departureTime;
-
- lastArrival = arrival;
- lastArrivalTime = arrivalTime;
- }
- else if (mDetFine.group(8) != null)
- {
- final String departure = ParserUtils.resolveEntities(mDetFine.group(8));
- if (departure != null && firstDeparture == null)
- firstDeparture = departure;
-
- final String min = mDetFine.group(9);
-
- final String arrival = ParserUtils.resolveEntities(mDetFine.group(10));
-
- if (parts.size() > 0 && parts.get(parts.size() - 1) instanceof Connection.Footway)
- {
- final Connection.Footway lastFootway = (Connection.Footway) parts.remove(parts.size() - 1);
- parts.add(new Connection.Footway(lastFootway.min + Integer.parseInt(min), 0, lastFootway.departure, 0, arrival));
- }
- else
- {
- parts.add(new Connection.Footway(Integer.parseInt(min), 0, departure, 0, arrival));
- }
-
- lastArrival = arrival;
- }
- }
- else
- {
- throw new IllegalArgumentException("cannot parse '" + set + "' on " + uri);
- }
- }
-
- if (firstDepartureTime == null && lastArrivalTime == null && parts.size() == 1 && parts.get(0) instanceof Connection.Footway)
- {
- final Calendar calendar = new GregorianCalendar();
- firstDepartureTime = calendar.getTime();
- calendar.add(Calendar.MINUTE, ((Connection.Footway) parts.get(0)).min);
- lastArrivalTime = calendar.getTime();
- }
-
- return new GetConnectionDetailsResult(new Date(), new Connection(ParserUtils.extractId(uri), uri, firstDepartureTime, lastArrivalTime,
- null, null, 0, firstDeparture, 0, lastArrival, parts));
- }
- else
- {
- if (P_CONNECTION_DETAILS_ERRORS.matcher(page).find())
- throw new SessionExpiredException();
- else
- throw new IOException(page.toString());
- }
- }
-
- private static Date upTime(final Date lastTime, Date time)
- {
- while (time.before(lastTime))
- time = ParserUtils.addDays(time, 1);
-
- lastTime.setTime(time.getTime());
-
- return time;
- }
-
@Override
protected String commandLink(final String sessionId, final String command)
{
- return null;
+ final StringBuilder uri = new StringBuilder();
+ uri.append(API_BASE);
+ uri.append("XSLT_TRIP_REQUEST2");
+ uri.append("?sessionID=").append(sessionId);
+ uri.append("&command=").append(command);
+ return uri.toString();
}
public String departuresQueryUri(final String stationId, final int maxDepartures)
@@ -534,172 +180,6 @@ public class MvvProvider extends AbstractEfaProvider
return uri.toString();
}
- private static final Pattern P_NORMALIZE_LINE_TRAM = Pattern.compile("[12]\\d");
- private static final Pattern P_NORMALIZE_LINE_NACHTTRAM = Pattern.compile("N[12]\\d");
- private static final Pattern P_NORMALIZE_LINE_METROBUS = Pattern.compile("[56]\\d");
- private static final Pattern P_NORMALIZE_LINE_STADTBUS = Pattern.compile("1\\d{2}");
- private static final Pattern P_NORMALIZE_LINE_NACHTBUS = Pattern.compile("N[48]\\d");
- private static final Pattern P_NORMALIZE_LINE_REGIONALBUS = Pattern.compile("\\d{3}[A-Z]?");
- private static final Pattern P_NORMALIZE_LINE_NUMBER = Pattern.compile("\\d{4}");
-
- private String normalizeLine(final String product, final String line)
- {
- if (product == null)
- {
- if (P_NORMALIZE_LINE_METROBUS.matcher(line).matches())
- return "B" + line;
- if (P_NORMALIZE_LINE_STADTBUS.matcher(line).matches())
- return "B" + line;
- if (P_NORMALIZE_LINE_NACHTBUS.matcher(line).matches())
- return "B" + line;
- if (line.equals("N117")) // Ersatzbus für N17
- return "BN117";
- if (P_NORMALIZE_LINE_REGIONALBUS.matcher(line).matches())
- return "B" + line;
- if (line.equals("Schienenersatzverkehr"))
- return "BSEV";
- if (line.startsWith("MVV-Ruftaxi "))
- return "B" + line;
- if (P_NORMALIZE_LINE_TRAM.matcher(line).matches())
- return "T" + line;
- if (P_NORMALIZE_LINE_NACHTTRAM.matcher(line).matches())
- return "T" + line;
- if (LINES.containsKey("S" + line))
- return "S" + line;
- if (line.equals("S20/27"))
- return "S" + line;
- if (LINES.containsKey("U" + line))
- return "U" + line;
- if (line.startsWith("D "))
- return "R" + line;
- if (line.startsWith("RE "))
- return "R" + line;
- if (line.startsWith("RB "))
- return "R" + line;
- if (line.startsWith("ALX ")) // Alex
- return "R" + line;
- if (line.startsWith("BOB ")) // Bayerische Oberlandbahn
- return "R" + line;
- if (line.startsWith("VBG ")) // Vogtlandbahn
- return "R" + line;
- if (line.startsWith("ICE "))
- return "I" + line;
- if (line.startsWith("IC "))
- return "I" + line;
- if (line.startsWith("EC "))
- return "I" + line;
- if (line.startsWith("CNL "))
- return "I" + line;
- if (P_NORMALIZE_LINE_NUMBER.matcher(line).matches())
- return "?" + line;
-
- throw new IllegalStateException("cannot normalize null product, line " + line);
- }
- else if (product.equals("Bus"))
- {
- if (line.startsWith("Bus"))
- return "B" + line.substring(4);
- else if (line.startsWith("StadtBus"))
- return "B" + line.substring(9);
- else if (line.startsWith("MetroBus"))
- return "B" + line.substring(9);
- else if (line.startsWith("Regionalbus"))
- return "B" + line.substring(12);
- else
- return "B" + line;
- }
- else if (product.equals("Tram"))
- {
- if (line.startsWith("Tram"))
- return "T" + line.substring(5);
- else
- return "T" + line;
- }
- else if (product.equals("U-Bahn"))
- {
- if (line.startsWith("U-Bahn"))
- return "U" + line.substring(7);
- else
- return "U" + line;
- }
- else if (product.equals("S-Bahn"))
- {
- if (line.startsWith("S-Bahn"))
- return "S" + line.substring(7);
- else
- return "S" + line;
- }
- else if (product.equals("Zug"))
- {
- final String[] lineParts = line.split("\\s+");
- final String type = lineParts[0];
- final String number = lineParts[1];
- if (type.equals("IC"))
- return "I" + type + number;
- if (type.equals("ICE"))
- return "I" + type + number;
- if (type.equals("EC"))
- return "I" + type + number;
- if (type.equals("EN")) // EuroNight
- return "I" + type + number;
- if (type.equals("CNL"))
- return "I" + type + number;
- if (type.equals("RJ")) // Railjet, Österreich
- return "I" + type + number;
- if (type.equals("IRE")) // Franken-Sachsen-Express
- return "I" + type + number;
- if (type.equals("RB"))
- return "R" + type + number;
- if (type.equals("RE"))
- return "R" + type + number;
- if (type.equals("D"))
- return "R" + type + number;
- if (type.equals("BOB"))
- return "R" + type + number;
- if (type.equals("BRB")) // Bayerische Regiobahn
- return "R" + type + number;
- if (type.equals("ALX")) // Länderbahn und Vogtlandbahn
- return "R" + type + number;
- if (type.equals("ERB")) // Eurobahn
- return "R" + type + number;
- if (type.equals("VBG")) // Vogtlandbahn
- return "R" + line;
-
- throw new IllegalStateException("cannot normalize product " + product + " line " + line);
- }
- else if (product.equals("Schiff"))
- {
- return "F" + line;
- }
- else if (product.equals("Seilbahn")) // strangely marked as 'Seilbahn', but means 'Schienenersatzverkehr'
- {
- return "BSEV" + line;
- }
-
- throw new IllegalStateException("cannot normalize product " + product + " line " + line);
- }
-
- private static Date parseDate(final String day, final String month, final String year)
- {
- final Calendar calendar = new GregorianCalendar();
- calendar.clear();
- calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(day));
- calendar.set(Calendar.MONTH, parseMonth(month));
- calendar.set(Calendar.YEAR, Integer.parseInt(year));
- return calendar.getTime();
- }
-
- private final static String[] MONTHS = new String[] { "Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sept", "Okt", "Nov", "Dez" };
-
- private static int parseMonth(final String month)
- {
- for (int m = 0; m < MONTHS.length; m++)
- if (MONTHS[m].equals(month))
- return m;
-
- throw new IllegalArgumentException("cannot parse month: " + month);
- }
-
private static final Map LINES = new HashMap();
static
diff --git a/test/de/schildbach/pte/MvvProviderTest.java b/test/de/schildbach/pte/MvvProviderTest.java
deleted file mode 100644
index 96c4c158..00000000
--- a/test/de/schildbach/pte/MvvProviderTest.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package de.schildbach.pte;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
-
-import java.util.regex.Matcher;
-
-import org.junit.Test;
-
-/**
- * @author Andreas Schildbach
- */
-public class MvvProviderTest
-{
- @Test
- public void trip()
- {
- final Matcher m = assertFineConnectionDetails("" //
- + "ab 04:27 Machern (Sachs) Gleis 2 \n" //
- + " | \n" //
- + "\n" //
- + " \n" //
- + " | \n" //
- + " | \n" //
- + "MRB 88040 Mitteldeutsche Regiobahn Richtung Leipzig Hbf | \n" //
- + " | \n" //
- + "an 04:47 Leipzig Hbf Gleis 19 | \n");
-
- assertNotNull(m.group(1)); // departureTime
- assertNotNull(m.group(2)); // departure
- assertNotNull(m.group(3)); // product
- }
-
- @Test
- public void trip2()
- {
- final Matcher m = assertFineConnectionDetails("" //
- + "ab 09:04 Hauptbahnhof Haupthalle Gleis 26 \n" //
- + " \n" //
- + " | \n" //
- + "\n" //
- + " \n" //
- + " | \n" //
- + " | \n" //
- + "RE 4006 RegionalExpress Richtung Nürnberg Hbf | \n" //
- + " | \n" //
- + "an 10:47 Nürnberg Hbf Gleis 12 | \n");
-
- assertNotNull(m.group(1)); // departureTime
- assertNotNull(m.group(2)); // departure
- assertNotNull(m.group(3)); // product
- }
-
- @Test
- public void tripSitzenbleiber()
- {
- final Matcher m = assertFineConnectionDetails("" //
- + "ab Neufahrn \n" //
- + " \n" //
- + " | \n" //
- + "\n" //
- + " \n" //
- + " | \n" //
- + " | \n" //
- + "nicht umsteigen | \n" //
- + " | \n" //
- + "an Neufahrn \n" //
- + " | \n");
-
- assertNull(m.group(1));
- assertNull(m.group(8));
- }
-
- @Test
- public void tripWithoutProduct()
- {
- final Matcher m = assertFineConnectionDetails("" //
- + "ab 07:46 Niederstraub. Abzw.Krottenthal \n" //
- + " \n" //
- + " | \n" //
- + " | \n" //
- + " | \n" //
- + "MVV-Ruftaxi 5621 Richtung Taufkirchen (Vils) Busbahnhof | \n" //
- + " | \n" //
- + "an 07:49 Dickarting \n" //
- + " | \n");
-
- assertNotNull(m.group(1)); // departureTime
- assertNotNull(m.group(2)); // departure
- assertNull(m.group(3)); // product
- }
-
- @Test
- public void footway()
- {
- final Matcher m = assertFineConnectionDetails("" //
- + "ab München Infanteriestraße 7 \n" //
- + " \n" //
- + " | \n" //
- + "\n" //
- + " \n" //
- + " | \n" //
- + " | \n" //
- + "Fußweg\n" //
- + " (ca. 3 Minuten)\n" //
- + " | \n" //
- + " | \n" //
- + "an Infanteriestraße Süd \n" //
- + " | \n");
-
- assertNotNull(m.group(8)); // departure
- }
-
- @Test
- public void footway2()
- {
- final Matcher m = assertFineConnectionDetails("" //
- + "ab Weimar Gleis 1 \n" //
- + " | \n" //
- + "\n" //
- + " \n" //
- + " | \n" //
- + " | \n" //
- + "Fußweg\n" //
- + "(ca. 2 Minuten)\n" //
- + " | \n" //
- + " | \n" //
- + "an Weimar Gleis 2 | \n");
-
- assertNotNull(m.group(8)); // departure
- }
-
- private Matcher assertFineConnectionDetails(String s)
- {
- Matcher m = MvvProvider.P_CONNECTION_DETAILS_FINE.matcher(s);
- assertTrue(m.matches());
-
- // ParserUtils.printGroups(m);
-
- return m;
- }
-}
|