use xml parser for departures query

git-svn-id: https://public-transport-enabler.googlecode.com/svn/trunk@702 0924bc21-9374-b0fa-ee44-9ff1593b38f0
This commit is contained in:
andreas.schildbach@gmail.com 2011-06-15 19:23:38 +00:00
parent 83a83b516e
commit cbd26e8c2c

View file

@ -422,119 +422,126 @@ public abstract class AbstractHafasProvider implements NetworkProvider
} }
} }
private static final Pattern P_XML_QUERY_DEPARTURES_COARSE = Pattern.compile( private static final Pattern P_XML_QUERY_DEPARTURES_DELAY = Pattern.compile("(?:-|k\\.A\\.?|cancel|\\+?\\s*(\\d+))");
"\\G<Journey ([^>]*?)(?:/>|><HIMMessage ([^>]*?)/></Journey>)(?:\n|\\z)", Pattern.DOTALL);
private static final Pattern P_XML_QUERY_DEPARTURES_FINE = Pattern.compile("" //
+ "fpTime\\s*=\"(\\d{1,2}:\\d{2})\"\\s*" // time
+ "fpDate\\s*=\"(\\d{2}[\\.-]\\d{2}[\\.-]\\d{2}|\\d{4}-\\d{2}-\\d{2})\"\\s*" // date
+ "delay\\s*=\"(?:-|k\\.A\\.?|cancel|\\+?\\s*(\\d+))\"\\s*" // delay
+ "(?:e_delay\\s*=\"\\d+\"\\s*)?" // (???)
+ "(?:platform\\s*=\"([^\"]*)\"\\s*)?" // position
+ "(?:newpl\\s*=\"([^\"]*)\"\\s*)?" //
+ "(?:targetLoc\\s*=\"([^\"]*)\"\\s*)?" // destination
+ "(?:hafasname\\s*=\"([^\"]*)\"\\s*)?" // line
+ "(?:dirnr\\s*=\"(\\d+)\"\\s*)?" // destination id
+ "prod\\s*=\"([^\"]*)\"\\s*" // line
+ "(?:class\\s*=\"([^\"]*)\"\\s*)?" // class
+ "(?:dir\\s*=\"([^\"]*)\"\\s*)?" // destination
+ "(?:capacity\\s*=\"([^\"]*)\"\\s*)?" // capacity 1st class|2nd class
+ "(?:depStation\\s*=\"(.*?)\"\\s*)?" //
+ "(?:delayReason\\s*=\"([^\"]*)\"\\s*)?" // message
+ "(?:is_reachable\\s*=\"[^\"]*\"\\s*)?" // (???)
+ "(?:disableTrainInfo\\s*=\"[^\"]*\"\\s*)?" // (???)
);
private static final Pattern P_XML_QUERY_DEPARTURES_MESSAGES = Pattern.compile("<Err code=\"([^\"]*)\" text=\"([^\"]*)\"");
protected QueryDeparturesResult xmlQueryDepartures(final String uri, final int stationId) throws IOException protected QueryDeparturesResult xmlQueryDepartures(final String uri, final int stationId) throws IOException
{ {
// scrape page // System.out.println(uri);
final CharSequence page = ParserUtils.scrape(uri);
InputStream is = null;
try
{
is = ParserUtils.scrapeInputStream(uri);
final XmlPullParserFactory factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), null);
final XmlPullParser pp = factory.newPullParser();
pp.setInput(is, DEFAULT_ENCODING);
pp.nextTag();
final QueryDeparturesResult result = new QueryDeparturesResult(); final QueryDeparturesResult result = new QueryDeparturesResult();
final List<Departure> departures = new ArrayList<Departure>(8);
// parse page if (XmlPullUtil.test(pp, "Err"))
final Matcher mMessage = P_XML_QUERY_DEPARTURES_MESSAGES.matcher(page);
if (mMessage.find())
{ {
final String code = mMessage.group(1); final String code = XmlPullUtil.attr(pp, "code");
final String text = mMessage.group(2); final String text = XmlPullUtil.attr(pp, "text");
if (code.equals("H730")) // Your input is not valid if (code.equals("H730")) // Your input is not valid
return new QueryDeparturesResult(QueryDeparturesResult.Status.INVALID_STATION); return new QueryDeparturesResult(QueryDeparturesResult.Status.INVALID_STATION);
if (code.equals("H890")) if (code.equals("H890"))
{ {
result.stationDepartures.add(new StationDepartures(new Location(LocationType.STATION, stationId), result.stationDepartures.add(new StationDepartures(new Location(LocationType.STATION, stationId), Collections
Collections.<Departure> emptyList(), null)); .<Departure> emptyList(), null));
return result; return result;
} }
throw new IllegalArgumentException("unknown error " + code + ", " + text); throw new IllegalArgumentException("unknown error " + code + ", " + text);
} }
final List<Departure> departures = new ArrayList<Departure>(8); while (XmlPullUtil.test(pp, "Journey"))
final Matcher mCoarse = P_XML_QUERY_DEPARTURES_COARSE.matcher(page);
while (mCoarse.find())
{ {
// TODO parse HIMMessage final String fpTime = XmlPullUtil.attr(pp, "fpTime");
final String fpDate = XmlPullUtil.attr(pp, "fpDate");
final String delay = XmlPullUtil.attr(pp, "delay");
// TODO e_delay
final String platform = pp.getAttributeValue(null, "platform");
// TODO newpl
final String targetLoc = pp.getAttributeValue(null, "targetLoc");
// TODO hafasname
final String dirnr = pp.getAttributeValue(null, "dirnr");
String prod = XmlPullUtil.attr(pp, "prod");
final String classStr = pp.getAttributeValue(null, "class");
final String dir = pp.getAttributeValue(null, "dir");
final String capacityStr = pp.getAttributeValue(null, "capacity");
final String depStation = pp.getAttributeValue(null, "depStation");
final String delayReason = pp.getAttributeValue(null, "delayReason");
// TODO is_reachable
// TODO disableTrainInfo
final Matcher mFine = P_XML_QUERY_DEPARTURES_FINE.matcher(mCoarse.group(1)); if (depStation == null)
if (mFine.matches())
{
if (mFine.group(13) == null)
{ {
final Calendar plannedTime = new GregorianCalendar(timeZone()); final Calendar plannedTime = new GregorianCalendar(timeZone());
plannedTime.clear(); plannedTime.clear();
ParserUtils.parseEuropeanTime(plannedTime, mFine.group(1)); ParserUtils.parseEuropeanTime(plannedTime, fpTime);
final String dateStr = mFine.group(2); if (fpDate.length() == 8)
if (dateStr.length() == 8) ParserUtils.parseGermanDate(plannedTime, fpDate);
ParserUtils.parseGermanDate(plannedTime, dateStr); else if (fpDate.length() == 10)
else if (dateStr.length() == 10) ParserUtils.parseIsoDate(plannedTime, fpDate);
ParserUtils.parseIsoDate(plannedTime, dateStr);
else else
throw new IllegalStateException("cannot parse: '" + dateStr + "'"); throw new IllegalStateException("cannot parse: '" + fpDate + "'");
final Calendar predictedTime; final Calendar predictedTime;
if (mFine.group(3) != null) if (delay != null)
{
final Matcher m = P_XML_QUERY_DEPARTURES_DELAY.matcher(delay);
if (m.matches())
{
if (m.group(1) != null)
{ {
predictedTime = new GregorianCalendar(timeZone()); predictedTime = new GregorianCalendar(timeZone());
predictedTime.setTimeInMillis(plannedTime.getTimeInMillis()); predictedTime.setTimeInMillis(plannedTime.getTimeInMillis());
predictedTime.add(Calendar.MINUTE, Integer.parseInt(mFine.group(3))); predictedTime.add(Calendar.MINUTE, Integer.parseInt(m.group(1)));
}
else
{
predictedTime = null;
}
}
else
{
throw new RuntimeException("cannot parse delay: '" + delay + "'");
}
} }
else else
{ {
predictedTime = null; predictedTime = null;
} }
// TODO parse newpl if present final String position = platform != null ? "Gl. " + ParserUtils.resolveEntities(platform) : null;
final String position = mFine.group(5) != null ? "Gl. " + ParserUtils.resolveEntities(mFine.group(5)) : null;
final String destination; final String destination;
if (mFine.group(11) != null) if (dir != null)
destination = ParserUtils.resolveEntities(mFine.group(11)).trim(); destination = dir.trim();
else if (mFine.group(6) != null) else if (targetLoc != null)
destination = ParserUtils.resolveEntities(mFine.group(6)).trim(); destination = targetLoc.trim();
else else
destination = null; destination = null;
final int destinationId; final int destinationId;
if (mFine.group(8) != null) if (dirnr != null)
destinationId = Integer.parseInt(mFine.group(8)); destinationId = Integer.parseInt(dirnr);
else else
destinationId = 0; destinationId = 0;
final String hafasName = ParserUtils.resolveEntities(mFine.group(7));
String prod = ParserUtils.resolveEntities(mFine.group(9));
final Matcher m = P_NORMALIZE_LINE.matcher(prod); final Matcher m = P_NORMALIZE_LINE.matcher(prod);
if (m.matches()) if (m.matches())
prod = m.group(1) + m.group(2); prod = m.group(1) + m.group(2);
final char product = mFine.group(10) != null ? intToProduct(Integer.parseInt(mFine.group(10))) : 0; final char product = classStr != null ? intToProduct(Integer.parseInt(classStr)) : 0;
final String line = product != 0 ? product + prod : normalizeLine(prod); final String line = product != 0 ? product + prod : normalizeLine(prod);
final String capacityStr = mFine.group(12);
final int[] capacity; final int[] capacity;
if (capacityStr != null && !"0|0".equals(capacityStr)) if (capacityStr != null && !"0|0".equals(capacityStr))
{ {
@ -546,11 +553,10 @@ public abstract class AbstractHafasProvider implements NetworkProvider
capacity = null; capacity = null;
} }
final String messageStr = mFine.group(13);
final String message; final String message;
if (messageStr != null) if (delayReason != null)
{ {
final String msg = ParserUtils.resolveEntities(messageStr).trim(); final String msg = delayReason.trim();
message = msg.length() > 0 ? msg : null; message = msg.length() > 0 ? msg : null;
} }
else else
@ -558,19 +564,35 @@ public abstract class AbstractHafasProvider implements NetworkProvider
message = null; message = null;
} }
departures.add(new Departure(plannedTime.getTime(), predictedTime != null ? predictedTime.getTime() : null, new Line(null, line, final Departure departure = new Departure(plannedTime.getTime(), predictedTime != null ? predictedTime.getTime() : null,
line != null ? lineColors(line) : null), position, destinationId, destination, capacity, message)); new Line(null, line, line != null ? lineColors(line) : null), position, destinationId, destination, capacity, message);
departures.add(departure);
} }
if (pp.isEmptyElementTag())
{
XmlPullUtil.next(pp);
} }
else else
{ {
throw new IllegalArgumentException("cannot parse '" + mCoarse.group(1) + "' on " + uri); XmlPullUtil.enter(pp, "Journey");
XmlPullUtil.exit(pp, "Journey");
} }
} }
result.stationDepartures.add(new StationDepartures(new Location(LocationType.STATION, stationId), departures, null)); result.stationDepartures.add(new StationDepartures(new Location(LocationType.STATION, stationId), departures, null));
return result; return result;
} }
catch (final XmlPullParserException x)
{
throw new RuntimeException(x);
}
finally
{
if (is != null)
is.close();
}
}
public QueryConnectionsResult queryConnections(Location from, Location via, Location to, final Date date, final boolean dep, public QueryConnectionsResult queryConnections(Location from, Location via, Location to, final Date date, final boolean dep,
final String products, final WalkSpeed walkSpeed) throws IOException final String products, final WalkSpeed walkSpeed) throws IOException