diff --git a/enabler/src/de/schildbach/pte/AbstractHafasProvider.java b/enabler/src/de/schildbach/pte/AbstractHafasProvider.java index 3f0a65c6..af61c56d 100644 --- a/enabler/src/de/schildbach/pte/AbstractHafasProvider.java +++ b/enabler/src/de/schildbach/pte/AbstractHafasProvider.java @@ -702,8 +702,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider if (classChar == 0) throw new IllegalArgumentException(); // could check for type consistency here - final String lineStr = classChar + prodLine.label.substring(1); - line = new Line(null, lineStr, lineStyle(lineStr)); + line = newLine(classChar, prodLine.label.substring(1)); } else { @@ -1730,7 +1729,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider final int type = is.readShortReverse(); - final String lineStr = strings.read(is); + final String lineName = strings.read(is); final String plannedDeparturePosition = normalizePosition(strings.read(is)); final String plannedArrivalPosition = normalizePosition(strings.read(is)); @@ -1743,6 +1742,8 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider is.skipBytes(attrsOffset + partAttrIndex * 4); String directionStr = null; int lineClass = 0; + String lineCategory = null; + String lineOperator = null; while (true) { final String key = strings.read(is); @@ -1752,10 +1753,17 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider directionStr = strings.read(is); else if (key.equals("Class")) lineClass = Integer.parseInt(strings.read(is)); + else if (key.equals("Category")) + lineCategory = strings.read(is); + else if (key.equals("Operator")) + lineOperator = strings.read(is); else is.skipBytes(2); } + if (lineCategory == null && lineName != null) + lineCategory = categoryFromName(lineName); + is.reset(); is.skipBytes(connectionDetailsPtr + connectionDetailsOffset + connectionDetailsPartOffset + iPart * connectionDetailsPartSize); @@ -1831,11 +1839,15 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider { part = new Connection.Footway(min, transfer, departure, arrival, null); } - } else if (type == 2) { - final Line line = parseLineWithoutType(lineStr); + final char lineProduct; + if (lineClass != 0) + lineProduct = intToProduct(lineClass); + else + lineProduct = normalizeType(lineCategory); + final Line line = newLine(lineProduct, normalizeLineName(lineName)); final Location direction = directionStr != null ? new Location(LocationType.ANY, 0, null, directionStr) : null; part = new Connection.Trip(line, direction, plannedDepartureTime != 0 ? new Date(plannedDepartureTime) : null, @@ -1955,7 +1967,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider while ((c = reader.read()) != 0) builder.append((char) c); - return builder.toString(); + return builder.toString().trim(); } finally { @@ -2635,7 +2647,33 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider return 0; } + private static final Pattern P_NORMALIZE_LINE_NAME_BUS = Pattern.compile("bus\\s+(.*)", Pattern.CASE_INSENSITIVE); protected static final Pattern P_NORMALIZE_LINE = Pattern.compile("([A-Za-zßÄÅäáàâåéèêíìîÖöóòôÜüúùûØ/]+)[\\s-]*([^#]*).*"); + + protected String normalizeLineName(final String lineName) + { + final Matcher mBus = P_NORMALIZE_LINE_NAME_BUS.matcher(lineName); + if (mBus.matches()) + return mBus.group(1); + + final Matcher m = P_NORMALIZE_LINE.matcher(lineName); + if (m.matches()) + return m.group(1) + m.group(2); + + return lineName; + } + + private static final Pattern P_CATEGORY_FROM_NAME = Pattern.compile("([A-Za-zßÄÅäáàâåéèêíìîÖöóòôÜüúùûØ]+).*"); + + protected final String categoryFromName(final String lineName) + { + final Matcher m = P_CATEGORY_FROM_NAME.matcher(lineName); + if (m.matches()) + return m.group(1); + else + return lineName; + } + private static final Pattern P_NORMALIZE_LINE_BUS = Pattern.compile("(?:Bus|BUS)\\s*(.*)"); private static final Pattern P_NORMALIZE_LINE_TRAM = Pattern.compile("(?:Tram|Str|STR)\\s*(.*)"); @@ -2675,35 +2713,6 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider } } - protected Line parseLineWithoutType(final String line) - { - if (line == null || line.length() == 0) - return null; - - final Matcher mBus = P_NORMALIZE_LINE_BUS.matcher(line); - if (mBus.matches()) - return newLine('B', mBus.group(1)); - - final Matcher mTram = P_NORMALIZE_LINE_TRAM.matcher(line); - if (mTram.matches()) - return newLine('T', mTram.group(1)); - - final Matcher m = P_NORMALIZE_LINE.matcher(line); - if (m.matches()) - { - final String type = m.group(1); - final String number = m.group(2); - - final char normalizedType = normalizeType(type); - if (normalizedType != 0) - return newLine(normalizedType, type + number); - - throw new IllegalStateException("cannot normalize type '" + type + "' number '" + number + "' line '" + line + "'"); - } - - throw new IllegalStateException("cannot normalize line " + line); - } - protected static final Pattern P_NORMALIZE_LINE_AND_TYPE = Pattern.compile("([^#]*)#(.*)"); private static final Pattern P_NORMALIZE_LINE_NUMBER = Pattern.compile("\\d{2,5}"); @@ -2756,9 +2765,9 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider throw new IllegalStateException("cannot normalize line#type '" + lineAndType + "'"); } - protected final Line newLine(final char product, final String name, final Line.Attr... attrs) + protected Line newLine(final char product, final String normalizedName, final Line.Attr... attrs) { - final String lineStr = product + (name != null ? name : "?"); + final String lineStr = product + (normalizedName != null ? normalizedName : "?"); if (attrs.length == 0) { diff --git a/enabler/src/de/schildbach/pte/BahnProvider.java b/enabler/src/de/schildbach/pte/BahnProvider.java index 10f00e06..fc1214fc 100644 --- a/enabler/src/de/schildbach/pte/BahnProvider.java +++ b/enabler/src/de/schildbach/pte/BahnProvider.java @@ -61,6 +61,33 @@ public final class BahnProvider extends AbstractHafasProvider return false; } + @Override + protected char intToProduct(final int value) + { + if (value == 1) + return 'I'; + if (value == 2) + return 'I'; + if (value == 4) + return 'R'; + if (value == 8) + return 'R'; + if (value == 16) + return 'S'; + if (value == 32) + return 'B'; + if (value == 64) + return 'F'; + if (value == 128) + return 'U'; + if (value == 256) + return 'T'; + if (value == 512) + return 'P'; + + throw new IllegalArgumentException("cannot handle: " + value); + } + @Override protected void setProductBits(final StringBuilder productBits, final char product) { @@ -204,6 +231,18 @@ public final class BahnProvider extends AbstractHafasProvider return queryMoreConnectionsBinary(contextObj, later, numConnections); } + private static final Pattern P_NORMALIZE_LINE_NAME_TRAM = Pattern.compile("str\\s+(.*)", Pattern.CASE_INSENSITIVE); + + @Override + protected String normalizeLineName(final String lineName) + { + final Matcher mTram = P_NORMALIZE_LINE_NAME_TRAM.matcher(lineName); + if (mTram.matches()) + return mTram.group(1); + + return super.normalizeLineName(lineName); + } + @Override protected char normalizeType(String type) { diff --git a/enabler/src/de/schildbach/pte/BvgProvider.java b/enabler/src/de/schildbach/pte/BvgProvider.java index bcaa5afc..9a84da1a 100644 --- a/enabler/src/de/schildbach/pte/BvgProvider.java +++ b/enabler/src/de/schildbach/pte/BvgProvider.java @@ -81,6 +81,29 @@ public final class BvgProvider extends AbstractHafasProvider return true; } + @Override + protected char intToProduct(final int value) + { + if (value == 1) + return 'S'; + if (value == 2) + return 'U'; + if (value == 4) + return 'T'; + if (value == 8) + return 'B'; + if (value == 16) + return 'F'; + if (value == 32) + return 'I'; + if (value == 64) + return 'R'; + if (value == 128) + return 'P'; + + throw new IllegalArgumentException("cannot handle: " + value); + } + @Override protected void setProductBits(final StringBuilder productBits, final char product) { @@ -325,7 +348,10 @@ public final class BvgProvider extends AbstractHafasProvider final Matcher mMsgsFine = P_DEPARTURES_LIVE_MSGS_FINE.matcher(mMsgsCoarse.group(1)); if (mMsgsFine.matches()) { - final Line line = parseLineWithoutType(ParserUtils.resolveEntities(mMsgsFine.group(1))); + final String lineName = ParserUtils.resolveEntities(mMsgsFine.group(1)); + final char linePproduct = normalizeType(categoryFromName(lineName)); + final Line line = newLine(linePproduct, normalizeLineName(lineName)); + final String message = ParserUtils.resolveEntities(mMsgsFine.group(3)).replace('\n', ' '); messages.put(line.label, message); } @@ -359,7 +385,9 @@ public final class BvgProvider extends AbstractHafasProvider else plannedTime = parsedTime.getTime(); - final Line line = parseLineWithoutType(ParserUtils.resolveEntities(mDepFine.group(3))); + final String lineName = ParserUtils.resolveEntities(mDepFine.group(3)); + final char lineProduct = normalizeType(categoryFromName(lineName)); + final Line line = newLine(lineProduct, normalizeLineName(lineName)); final String position = null; @@ -429,7 +457,9 @@ public final class BvgProvider extends AbstractHafasProvider final Date plannedTime = parsedTime.getTime(); - final Line line = parseLineWithoutType(ParserUtils.resolveEntities(mDepFine.group(2))); + final String lineName = ParserUtils.resolveEntities(mDepFine.group(2)); + final char lineProduct = normalizeType(categoryFromName(lineName)); + final Line line = newLine(lineProduct, normalizeLineName(lineName)); final String position = ParserUtils.resolveEntities(mDepFine.group(3)); @@ -509,51 +539,53 @@ public final class BvgProvider extends AbstractHafasProvider return queryMoreConnectionsBinary(contextObj, later, numConnections); } - private static final Pattern P_LINE_REGIONAL = Pattern.compile("Zug\\s+(\\d+)"); - private static final Pattern P_LINE_TRAM = Pattern.compile("Tram?\\s+([\\dA-Z/-]+)"); - private static final Pattern P_LINE_BUS = Pattern.compile("Bus\\s+([\\dA-Z/-]+)"); - private static final Pattern P_LINE_FERRY = Pattern.compile("F\\d+|WT"); - private static final Pattern P_LINE_NUMBER = Pattern.compile("\\d{4,}"); + private static final Pattern P_NORMALIZE_LINE_NAME_TRAM = Pattern.compile("(?:tra|tram)\\s+(.*)", Pattern.CASE_INSENSITIVE); @Override - protected Line parseLineWithoutType(final String line) + protected String normalizeLineName(final String lineName) { - if ("S41".equals(line)) - return newLine('S', "S41", Attr.CIRCLE_CLOCKWISE); - if ("S42".equals(line)) - return newLine('S', "S42", Attr.CIRCLE_ANTICLOCKWISE); - - if ("Bus S41".equals(line)) - return newLine('B', "S41", Attr.SERVICE_REPLACEMENT, Attr.CIRCLE_CLOCKWISE); - if ("Bus S42".equals(line)) - return newLine('B', "S42", Attr.SERVICE_REPLACEMENT, Attr.CIRCLE_ANTICLOCKWISE); - - if ("Bus TXL".equals(line)) - return newLine('B', "TXL", Attr.LINE_AIRPORT); - if ("S9".equals(line)) - return newLine('S', "S9", Attr.LINE_AIRPORT); - if ("S45".equals(line)) - return newLine('S', "S45", Attr.LINE_AIRPORT); - - final Matcher mRegional = P_LINE_REGIONAL.matcher(line); - if (mRegional.matches()) - return newLine('R', mRegional.group(1)); - - final Matcher mTram = P_LINE_TRAM.matcher(line); + final Matcher mTram = P_NORMALIZE_LINE_NAME_TRAM.matcher(lineName); if (mTram.matches()) - return newLine('T', mTram.group(1)); + return mTram.group(1); - final Matcher mBus = P_LINE_BUS.matcher(line); - if (mBus.matches()) - return newLine('B', mBus.group(1)); + return super.normalizeLineName(lineName); + } - if (P_LINE_FERRY.matcher(line).matches()) - return newLine('F', line); + @Override + protected Line newLine(final char product, final String normalizedName, final Attr... attrs) + { + if (product == 'S' && "S41".equals(normalizedName)) + return super.newLine(product, normalizedName, concatAttrs(attrs, Attr.CIRCLE_CLOCKWISE)); + if (product == 'S' && "S42".equals(normalizedName)) + return super.newLine(product, normalizedName, concatAttrs(attrs, Attr.CIRCLE_ANTICLOCKWISE)); - if (P_LINE_NUMBER.matcher(line).matches()) - return newLine('R', line); + if (product == 'B' && "S41".equals(normalizedName)) + return super.newLine(product, normalizedName, concatAttrs(attrs, Attr.SERVICE_REPLACEMENT, Attr.CIRCLE_CLOCKWISE)); + if (product == 'B' && "S42".equals(normalizedName)) + return super.newLine(product, normalizedName, concatAttrs(attrs, Attr.SERVICE_REPLACEMENT, Attr.CIRCLE_ANTICLOCKWISE)); - return super.parseLineWithoutType(line); + if (product == 'B' && "TXL".equals(normalizedName)) + return super.newLine(product, normalizedName, concatAttrs(attrs, Attr.LINE_AIRPORT)); + if (product == 'S' && "S9".equals(normalizedName)) + return super.newLine(product, normalizedName, concatAttrs(attrs, Attr.LINE_AIRPORT)); + if (product == 'S' && "S45".equals(normalizedName)) + return super.newLine(product, normalizedName, concatAttrs(attrs, Attr.LINE_AIRPORT)); + + return super.newLine(product, normalizedName, attrs); + } + + private Attr[] concatAttrs(final Attr[] attrs1, final Attr... attrs2) + { + final int attrs1length = attrs1.length; + final int attrs2length = attrs2.length; + + final Attr[] newAttrs = new Attr[attrs1length + attrs2length]; + for (int i = 0; i < attrs1length; i++) + newAttrs[i] = attrs1[i]; + for (int i = 0; i < attrs2length; i++) + newAttrs[attrs1length + i] = attrs2[i]; + + return newAttrs; } @Override @@ -564,6 +596,11 @@ public final class BvgProvider extends AbstractHafasProvider if ("AUSFL".equals(ucType)) // Umgebung Berlin return 'R'; + if ("F".equals(ucType)) + return 'F'; + if ("WT".equals(ucType)) // Wassertaxi + return 'F'; + final char t = super.normalizeType(type); if (t != 0) return t; diff --git a/enabler/src/de/schildbach/pte/NsProvider.java b/enabler/src/de/schildbach/pte/NsProvider.java index 54fc070f..71de0ae2 100644 --- a/enabler/src/de/schildbach/pte/NsProvider.java +++ b/enabler/src/de/schildbach/pte/NsProvider.java @@ -57,6 +57,15 @@ public class NsProvider extends AbstractHafasProvider return false; } + @Override + protected char intToProduct(final int value) + { + if (value == 0) + return '?'; + + throw new IllegalArgumentException("cannot handle: " + value); + } + @Override protected void setProductBits(final StringBuilder productBits, final char product) { diff --git a/enabler/src/de/schildbach/pte/RmvProvider.java b/enabler/src/de/schildbach/pte/RmvProvider.java index e6bf4560..c0b099cc 100644 --- a/enabler/src/de/schildbach/pte/RmvProvider.java +++ b/enabler/src/de/schildbach/pte/RmvProvider.java @@ -104,6 +104,35 @@ public class RmvProvider extends AbstractHafasProvider } } + @Override + protected char intToProduct(final int value) + { + if (value == 1) + return 'I'; + if (value == 2) + return 'I'; + if (value == 4) + return 'R'; + if (value == 8) + return 'S'; + if (value == 16) + return 'U'; + if (value == 32) + return 'T'; + if (value == 64) + return 'B'; + if (value == 128) + return 'B'; + if (value == 256) + return 'F'; + if (value == 512) + return 'P'; + if (value == 1024) + return 'R'; + + throw new IllegalArgumentException("cannot handle: " + value); + } + private static final String[] PLACES = { "Frankfurt (Main)", "Offenbach (Main)", "Mainz", "Wiesbaden", "Marburg", "Kassel", "Hanau", "Göttingen", "Darmstadt", "Aschaffenburg", "Berlin", "Fulda" };