From 3c5dc7c3287af01a7e8265408550312cae177573 Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Sun, 11 Jan 2015 23:16:16 +0100 Subject: [PATCH] Introduce AbstractNetworkProvider.parsePosition() for custom parsable positions. --- .../schildbach/pte/AbstractEfaProvider.java | 49 ++++++++----------- .../schildbach/pte/AbstractHafasProvider.java | 12 ++--- .../pte/AbstractNetworkProvider.java | 31 ++++++++++++ .../src/de/schildbach/pte/InvgProvider.java | 3 +- .../src/de/schildbach/pte/MvgProvider.java | 14 ++++++ .../src/de/schildbach/pte/MvvProvider.java | 25 ++++++++++ .../src/de/schildbach/pte/SeptaProvider.java | 3 +- enabler/src/de/schildbach/pte/ShProvider.java | 3 +- .../src/de/schildbach/pte/dto/Position.java | 28 +++++++++-- 9 files changed, 122 insertions(+), 46 deletions(-) diff --git a/enabler/src/de/schildbach/pte/AbstractEfaProvider.java b/enabler/src/de/schildbach/pte/AbstractEfaProvider.java index 71218422..4c6b5489 100644 --- a/enabler/src/de/schildbach/pte/AbstractEfaProvider.java +++ b/enabler/src/de/schildbach/pte/AbstractEfaProvider.java @@ -1620,7 +1620,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider new LinkedList(), new LinkedList()); } - final Position position = normalizePlatformName(XmlPullUtil.optAttr(pp, "platformName", null)); + final Position position = parsePosition(XmlPullUtil.optAttr(pp, "platformName", null)); XmlPullUtil.enter(pp, "itdDeparture"); @@ -1726,7 +1726,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider XmlPullUtil.enter(pp, "r"); final String assignedId = XmlPullUtil.valueTag(pp, "id"); XmlPullUtil.valueTag(pp, "a"); - final Position position = new Position(XmlPullUtil.optValueTag(pp, "pl", null)); + final Position position = super.parsePosition(XmlPullUtil.optValueTag(pp, "pl", null)); XmlPullUtil.skipExit(pp, "r"); /* final Point positionCoordinate = */coordStrToPoint(XmlPullUtil.optValueTag(pp, "c", null)); @@ -2438,7 +2438,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider final Location departureLocation = processItdPointAttributes(pp); if (firstDepartureLocation == null) firstDepartureLocation = departureLocation; - final Position departurePosition = normalizePlatformName(XmlPullUtil.optAttr(pp, "platformName", null)); + final Position departurePosition = parsePosition(XmlPullUtil.optAttr(pp, "platformName", null)); XmlPullUtil.enter(pp, "itdPoint"); if (XmlPullUtil.test(pp, "itdMapItemList")) XmlPullUtil.next(pp); @@ -2462,7 +2462,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider throw new IllegalStateException(); final Location arrivalLocation = processItdPointAttributes(pp); lastArrivalLocation = arrivalLocation; - final Position arrivalPosition = normalizePlatformName(XmlPullUtil.optAttr(pp, "platformName", null)); + final Position arrivalPosition = parsePosition(XmlPullUtil.optAttr(pp, "platformName", null)); XmlPullUtil.enter(pp, "itdPoint"); if (XmlPullUtil.test(pp, "itdMapItemList")) XmlPullUtil.next(pp); @@ -2618,7 +2618,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider { final Location stopLocation = processItdPointAttributes(pp); - final Position stopPosition = normalizePlatformName(XmlPullUtil.optAttr(pp, "platformName", null)); + final Position stopPosition = parsePosition(XmlPullUtil.optAttr(pp, "platformName", null)); XmlPullUtil.enter(pp, "itdPoint"); XmlPullUtil.require(pp, "itdDateTime"); @@ -2880,7 +2880,7 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider XmlPullUtil.enter(pp, "r"); final String id = XmlPullUtil.valueTag(pp, "id"); XmlPullUtil.optValueTag(pp, "a", null); - final Position position = new Position(XmlPullUtil.optValueTag(pp, "pl", null)); + final Position position = super.parsePosition(XmlPullUtil.optValueTag(pp, "pl", null)); final String place = normalizeLocationName(XmlPullUtil.optValueTag(pp, "pc", null)); final Point coord = coordStrToPoint(XmlPullUtil.optValueTag(pp, "c", null)); XmlPullUtil.skipExit(pp, "r"); @@ -3209,32 +3209,23 @@ public abstract class AbstractEfaProvider extends AbstractNetworkProvider return Currency.getInstance(currencyStr); } - private static final Pattern P_PLATFORM_NAME = Pattern.compile("(?:Gleis|Gl\\.|Bstg\\.)?\\s*" + // - "(\\d+)\\s*" + // - "(?:([A-Z])\\s*(?:-\\s*([A-Z]))?)?", Pattern.CASE_INSENSITIVE); + private static final Pattern P_POSITION = Pattern.compile( + "(?:Gleis|Gl\\.|Bahnsteig|Bstg\\.|Bussteig|Busstg\\.|Steig|Hp\\.|Stop|Pos\\.|Zone|Platform)?\\s*(.+)", Pattern.CASE_INSENSITIVE); - private static final Position normalizePlatformName(final String platformName) + @Override + protected Position parsePosition(final String position) { - if (platformName != null) - { - final Matcher m = P_PLATFORM_NAME.matcher(platformName); - if (m.matches()) - { - final String simple = Integer.toString(Integer.parseInt(m.group(1))); - if (m.group(2) != null && m.group(3) != null) - return new Position(simple + m.group(2) + "-" + m.group(3)); - else if (m.group(2) != null) - return new Position(simple + m.group(2)); - else - return new Position(simple); - } - else - { - return new Position(platformName); - } - } + if (position == null) + return null; - return null; + if (position.startsWith("Ri.") || position.startsWith("Richtung ")) + return null; + + final Matcher m = P_POSITION.matcher(position); + if (m.matches()) + return super.parsePosition(m.group(1)); + + return super.parsePosition(position); } private void appendLocation(final StringBuilder uri, final Location location, final String paramSuffix) diff --git a/enabler/src/de/schildbach/pte/AbstractHafasProvider.java b/enabler/src/de/schildbach/pte/AbstractHafasProvider.java index 3964d50f..f7fb5d8f 100644 --- a/enabler/src/de/schildbach/pte/AbstractHafasProvider.java +++ b/enabler/src/de/schildbach/pte/AbstractHafasProvider.java @@ -330,7 +330,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider throw new IllegalStateException("cannot handle: " + type); } - private static final Position parsePlatform(final XmlPullParser pp) throws XmlPullParserException, IOException + private final Position parsePlatform(final XmlPullParser pp) throws XmlPullParserException, IOException { XmlPullUtil.enter(pp, "Platform"); final String platformText = XmlPullUtil.valueTag(pp, "Text"); @@ -339,7 +339,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider if (platformText == null || platformText.length() == 0) return null; else - return new Position(platformText); + return parsePosition(platformText); } public SuggestLocationsResult suggestLocations(final CharSequence constraint) throws IOException @@ -627,7 +627,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider predictedTime = null; } - final Position position = platform != null ? new Position("Gl. " + ParserUtils.resolveEntities(platform)) : null; + final Position position = parsePosition(ParserUtils.resolveEntities(platform)); final String destinationName; if (dir != null) @@ -2272,7 +2272,7 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider } } - private static final Pattern P_POSITION_PLATFORM = Pattern.compile("Gleis\\s*([^\\s]*)\\s*", Pattern.CASE_INSENSITIVE); + private static final Pattern P_POSITION_PLATFORM = Pattern.compile("Gleis\\s*(.*)\\s*", Pattern.CASE_INSENSITIVE); private Position normalizePosition(final String position) { @@ -2281,9 +2281,9 @@ public abstract class AbstractHafasProvider extends AbstractNetworkProvider final Matcher m = P_POSITION_PLATFORM.matcher(position); if (!m.matches()) - return new Position(position); + return parsePosition(position); - return new Position(m.group(1)); + return parsePosition(m.group(1)); } public NearbyStationsResult queryNearbyStations(final Location location, final int maxDistance, final int maxStations) throws IOException diff --git a/enabler/src/de/schildbach/pte/AbstractNetworkProvider.java b/enabler/src/de/schildbach/pte/AbstractNetworkProvider.java index 53d169bd..d3fc605d 100644 --- a/enabler/src/de/schildbach/pte/AbstractNetworkProvider.java +++ b/enabler/src/de/schildbach/pte/AbstractNetworkProvider.java @@ -24,8 +24,11 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import de.schildbach.pte.dto.Point; +import de.schildbach.pte.dto.Position; import de.schildbach.pte.dto.Product; import de.schildbach.pte.dto.Style; @@ -157,4 +160,32 @@ public abstract class AbstractNetworkProvider implements NetworkProvider return normalized.toString(); } + + private static final Pattern P_NAME_SECTION = Pattern.compile("(\\d+)\\s*" + // + "([A-Z](?:\\s*-?\\s*[A-Z])?)?", Pattern.CASE_INSENSITIVE); + + private static final Pattern P_NAME_NOSW = Pattern.compile("(\\d+)\\s*" + // + "(Nord|Süd|Ost|West)", Pattern.CASE_INSENSITIVE); + + protected Position parsePosition(final String position) + { + if (position == null) + return null; + + final Matcher mSection = P_NAME_SECTION.matcher(position); + if (mSection.matches()) + { + final String name = Integer.toString(Integer.parseInt(mSection.group(1))); + if (mSection.group(2) != null) + return new Position(name, mSection.group(2).replaceAll("\\s+", "")); + else + return new Position(name); + } + + final Matcher mNosw = P_NAME_NOSW.matcher(position); + if (mNosw.matches()) + return new Position(Integer.toString(Integer.parseInt(mNosw.group(1))), mNosw.group(2).substring(0, 1)); + + return new Position(position); + } } diff --git a/enabler/src/de/schildbach/pte/InvgProvider.java b/enabler/src/de/schildbach/pte/InvgProvider.java index f1b6fca8..c0f76e23 100644 --- a/enabler/src/de/schildbach/pte/InvgProvider.java +++ b/enabler/src/de/schildbach/pte/InvgProvider.java @@ -250,8 +250,7 @@ public class InvgProvider extends AbstractHafasProvider destination = new Location(LocationType.ANY, null, null, destinationName); } - final Position position = mDepFine.group(7) != null ? new Position("Gl. " + ParserUtils.resolveEntities(mDepFine.group(7))) - : null; + final Position position = parsePosition(ParserUtils.resolveEntities(mDepFine.group(7))); final Departure dep = new Departure(plannedTime.getTime(), predictedTime != null ? predictedTime.getTime() : null, line, position, destination, null, null); diff --git a/enabler/src/de/schildbach/pte/MvgProvider.java b/enabler/src/de/schildbach/pte/MvgProvider.java index 57d667a0..95ce4035 100644 --- a/enabler/src/de/schildbach/pte/MvgProvider.java +++ b/enabler/src/de/schildbach/pte/MvgProvider.java @@ -17,6 +17,8 @@ package de.schildbach.pte; +import de.schildbach.pte.dto.Position; + /** * @author Andreas Schildbach */ @@ -34,4 +36,16 @@ public class MvgProvider extends AbstractEfaProvider { return NETWORK_ID; } + + @Override + protected Position parsePosition(final String position) + { + if (position == null) + return null; + + if (position.startsWith(" - ")) + return super.parsePosition(position.substring(3)); + + return super.parsePosition(position); + } } diff --git a/enabler/src/de/schildbach/pte/MvvProvider.java b/enabler/src/de/schildbach/pte/MvvProvider.java index c212f420..8d8d9a20 100644 --- a/enabler/src/de/schildbach/pte/MvvProvider.java +++ b/enabler/src/de/schildbach/pte/MvvProvider.java @@ -19,8 +19,11 @@ package de.schildbach.pte; import java.util.HashMap; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import de.schildbach.pte.dto.Point; +import de.schildbach.pte.dto.Position; import de.schildbach.pte.dto.Style; /** @@ -73,6 +76,28 @@ public class MvvProvider extends AbstractEfaProvider return super.parseLine(mot, symbol, name, longName, trainType, trainNum, trainName); } + private static final Pattern P_POSITION = Pattern.compile("(Fern|Regio|S-Bahn|U-Bahn|U\\d(?:/U\\d)*)\\s+(.*)"); + + @Override + protected Position parsePosition(final String position) + { + if (position == null) + return null; + + final Matcher m = P_POSITION.matcher(position); + if (m.matches()) + { + final char t = m.group(1).charAt(0); + final Position p = super.parsePosition(m.group(2)); + if (t == 'S' || t == 'U') + return new Position(p.name + "(" + t + ")", p.section); + else + return p; + } + + return super.parsePosition(position); + } + private static final Map STYLES = new HashMap(); static diff --git a/enabler/src/de/schildbach/pte/SeptaProvider.java b/enabler/src/de/schildbach/pte/SeptaProvider.java index ce194799..2ce21a8c 100644 --- a/enabler/src/de/schildbach/pte/SeptaProvider.java +++ b/enabler/src/de/schildbach/pte/SeptaProvider.java @@ -256,8 +256,7 @@ public class SeptaProvider extends AbstractHafasProvider destination = new Location(LocationType.ANY, null, null, destinationName); } - final Position position = mDepFine.group(7) != null ? new Position("Gl. " + ParserUtils.resolveEntities(mDepFine.group(7))) - : null; + final Position position = parsePosition(ParserUtils.resolveEntities(mDepFine.group(7))); final Departure dep = new Departure(plannedTime.getTime(), predictedTime != null ? predictedTime.getTime() : null, line, position, destination, null, null); diff --git a/enabler/src/de/schildbach/pte/ShProvider.java b/enabler/src/de/schildbach/pte/ShProvider.java index 42de136b..fdb1b71c 100644 --- a/enabler/src/de/schildbach/pte/ShProvider.java +++ b/enabler/src/de/schildbach/pte/ShProvider.java @@ -275,8 +275,7 @@ public class ShProvider extends AbstractHafasProvider destination = new Location(LocationType.ANY, null, null, destinationName); } - final Position position = mDepFine.group(6) != null ? new Position("Gl. " + ParserUtils.resolveEntities(mDepFine.group(6))) - : null; + final Position position = parsePosition(ParserUtils.resolveEntities(mDepFine.group(6))); final Departure dep = new Departure(plannedTime.getTime(), null, line, position, destination, null, null); diff --git a/enabler/src/de/schildbach/pte/dto/Position.java b/enabler/src/de/schildbach/pte/dto/Position.java index 1b737614..0a1397c1 100644 --- a/enabler/src/de/schildbach/pte/dto/Position.java +++ b/enabler/src/de/schildbach/pte/dto/Position.java @@ -25,18 +25,33 @@ import java.io.Serializable; public final class Position implements Serializable { public final String name; + public final String section; public Position(final String name) { + this(name, null); + } + + public Position(final String name, final String section) + { + if (name == null) + throw new IllegalArgumentException("name cannot be null"); + // else if (name.length() > 5) + // throw new IllegalArgumentException("name too long: " + name); + + if (section != null && section.length() > 3) + throw new IllegalArgumentException("section too long: " + section); + this.name = name; + this.section = section; } @Override public String toString() { - final StringBuilder builder = new StringBuilder("Position("); - builder.append(name != null ? name : "null"); - builder.append(")"); + final StringBuilder builder = new StringBuilder(name); + if (section != null) + builder.append(section); return builder.toString(); } @@ -48,7 +63,9 @@ public final class Position implements Serializable if (!(o instanceof Position)) return false; final Position other = (Position) o; - if (!nullSafeEquals(this.name, other.name)) + if (!this.name.equals(other.name)) + return false; + if (!nullSafeEquals(this.section, other.section)) return false; return true; } @@ -57,7 +74,8 @@ public final class Position implements Serializable public int hashCode() { int hashCode = 0; - hashCode += nullSafeHashCode(name); + hashCode += name.hashCode(); + hashCode += nullSafeHashCode(section); return hashCode; }