diff --git a/src/main/java/org/ligi/passandroid/model/BasePassbook.java b/src/main/java/org/ligi/passandroid/model/BasePassbook.java new file mode 100644 index 00000000..61e7112f --- /dev/null +++ b/src/main/java/org/ligi/passandroid/model/BasePassbook.java @@ -0,0 +1,97 @@ +package org.ligi.passandroid.model; + +import com.google.common.base.Optional; +import com.google.zxing.BarcodeFormat; + +import org.joda.time.DateTime; + +import java.util.ArrayList; +import java.util.List; + +public abstract class BasePassbook implements Passbook { + protected Optional organisation = Optional.absent(); + protected String type; + protected boolean passbook_valid = true; // be positive + protected String barcodeMessage; + protected BarcodeFormat barcodeFormat; + protected int backGroundColor; + protected int foregroundColor; + protected String description; + protected Optional relevantDate = Optional.absent(); + protected Optional expirationDate = Optional.absent(); + protected PassFieldList primaryFields, secondaryFields, backFields, auxiliaryFields, headerFields; + protected List locations = new ArrayList<>(); + + + @Override + public Optional getOrganisation() { + return organisation; + } + + @Override + public int getForegroundColor() { + return foregroundColor; + } + + @Override + public Optional getRelevantDate() { + return relevantDate; + } + + @Override + public Optional getExpirationDate() { + return expirationDate; + } + + @Override + public int getBackGroundColor() { + return backGroundColor; + } + + + @Override + public boolean isValid() { + return passbook_valid; + } + + @Override + public BarcodeFormat getBarcodeFormat() { + return barcodeFormat; + } + + @Override + public String getType() { + return type; + } + + @Override + public PassFieldList getPrimaryFields() { + return primaryFields; + } + + @Override + public PassFieldList getSecondaryFields() { + return secondaryFields; + } + + @Override + public PassFieldList getBackFields() { + return backFields; + } + + @Override + public PassFieldList getAuxiliaryFields() { + return auxiliaryFields; + } + + @Override + public PassFieldList getHeaderFields() { + return headerFields; + } + + @Override + public List getLocations() { + return locations; + } + +} diff --git a/src/main/java/org/ligi/passandroid/model/FilePathPassbook.java b/src/main/java/org/ligi/passandroid/model/FilePathPassbook.java index 3d373a07..f4f17972 100644 --- a/src/main/java/org/ligi/passandroid/model/FilePathPassbook.java +++ b/src/main/java/org/ligi/passandroid/model/FilePathPassbook.java @@ -4,6 +4,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; +import com.google.common.base.Optional; import com.google.zxing.BarcodeFormat; import org.joda.time.DateTime; @@ -18,29 +19,17 @@ import org.ligi.tracedroid.logging.Log; import java.io.File; import java.nio.charset.Charset; -import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class FilePathPassbook implements Passbook { +public class FilePathPassbook extends QuirkCorrectingPassbook { - private String path; - private String id; - private String type; - private boolean passbook_valid = true; // be positive - private String barcodeMessage; - private BarcodeFormat barcodeFormat; - private int backGroundColor; - private int foregroundColor; - private String description; - private DateTime relevantDate; - private PassFieldList primaryFields, secondaryFields, backFields, auxiliaryFields, headerFields; - private List locations = new ArrayList(); private JSONObject ticketJSONObject = null; private String plainJsonString; + private String path; + private String id; public static final String[] TYPES = new String[]{"coupon", "eventTicket", "boardingPass", "generic", "storeCard"}; @@ -114,12 +103,24 @@ public class FilePathPassbook implements Passbook { } if (pass_json != null) { - try { - relevantDate = new DateTime(pass_json.getString("relevantDate")); - } catch (JSONException e) { - } catch (IllegalArgumentException e) { - // be robust when it comes to bad dates - had a RL crash with "2013-12-25T00:00-57:00" here - // OK then we just have no date here + if (pass_json.has("relevantDate")) { + try { + relevantDate = Optional.of(new DateTime(pass_json.getString("relevantDate"))); + } catch (JSONException | IllegalArgumentException e) { + // be robust when it comes to bad dates - had a RL crash with "2013-12-25T00:00-57:00" here + // OK then we just have no date here + Tracker.get().trackException("problem parsing relevant date", e, false); + } + } + + if (pass_json.has("expirationDate")) { + try { + expirationDate = Optional.of(new DateTime(pass_json.getString("expirationDate"))); + } catch (JSONException | IllegalArgumentException e) { + // be robust when it comes to bad dates - had a RL crash with "2013-12-25T00:00-57:00" here + // OK then we just have no date here + Tracker.get().trackException("problem parsing expiration date", e, false); + } } try { @@ -194,6 +195,14 @@ public class FilePathPassbook implements Passbook { headerFields = new PassFieldList(ticketJSONObject, "headerFields"); } + try { + organisation = Optional.of(pass_json.getString("organizationName")); + + } catch (JSONException e) { + // ok - we have no organisation - big deal ..-) + } + + correctQuirks(); } public String findType(JSONObject obj) { @@ -235,33 +244,6 @@ public class FilePathPassbook implements Passbook { return description; } - public String getType() { - return type; - } - - public PassFieldList getPrimaryFields() { - return primaryFields; - } - - public PassFieldList getSecondaryFields() { - return secondaryFields; - } - - public PassFieldList getBackFields() { - return backFields; - } - - public PassFieldList getAuxiliaryFields() { - return auxiliaryFields; - } - - public PassFieldList getHeaderFields() { - return headerFields; - } - - public List getLocations() { - return locations; - } private int parseColor(String color_str, int defaultValue) { if (color_str == null) { @@ -298,13 +280,6 @@ public class FilePathPassbook implements Passbook { return defaultValue; } - public boolean isValid() { - return passbook_valid; - } - - public BarcodeFormat getBarcodeFormat() { - return barcodeFormat; - } public Bitmap getBarcodeBitmap(final int size) { if (barcodeMessage == null) { @@ -383,32 +358,18 @@ public class FilePathPassbook implements Passbook { return result; } - public int getBackGroundColor() { - return backGroundColor; - } - public String getPath() { return path; } - public int getForegroundColor() { - return foregroundColor; - } - - public boolean hasRelevantDate() { - return relevantDate != null; - } - - public DateTime getRelevantDate() { - return relevantDate; - } - public String getId() { return id; } + @Override public String getPlainJsonString() { return plainJsonString; } + } diff --git a/src/main/java/org/ligi/passandroid/model/Passbook.java b/src/main/java/org/ligi/passandroid/model/Passbook.java index a378e540..e6a8c5af 100644 --- a/src/main/java/org/ligi/passandroid/model/Passbook.java +++ b/src/main/java/org/ligi/passandroid/model/Passbook.java @@ -2,6 +2,7 @@ package org.ligi.passandroid.model; import android.graphics.Bitmap; +import com.google.common.base.Optional; import com.google.zxing.BarcodeFormat; import org.joda.time.DateTime; @@ -10,7 +11,6 @@ import java.util.List; public interface Passbook { - static final String[] TYPES = new String[]{"coupon", "eventTicket", "boardingPass", "generic", "storeCard"}; String getDescription(); @@ -47,11 +47,13 @@ public interface Passbook { int getForegroundColor(); - boolean hasRelevantDate(); + Optional getRelevantDate(); - DateTime getRelevantDate(); + Optional getExpirationDate(); String getId(); String getPlainJsonString(); + + Optional getOrganisation(); } diff --git a/src/main/java/org/ligi/passandroid/model/PrettifiedPassbookDecorator.java b/src/main/java/org/ligi/passandroid/model/PrettifiedPassbookDecorator.java deleted file mode 100644 index 063fd2fb..00000000 --- a/src/main/java/org/ligi/passandroid/model/PrettifiedPassbookDecorator.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.ligi.passandroid.model; - -import com.google.common.base.Optional; - -public class PrettifiedPassbookDecorator { - - private String prettifiedDescription; - private final Passbook sourcePassbook; - - public PrettifiedPassbookDecorator(Passbook sourcePassbook) { - this.sourcePassbook = sourcePassbook; - - // default is what we have - prettifiedDescription = sourcePassbook.getDescription(); - - careForAirBerlin(); - careForTUIFlight(); - } - - private void careForTUIFlight() { - if (sourcePassbook.getDescription().equals("TUIfly pass")) { - Optional originField = sourcePassbook.getPrimaryFields().getPassFieldForKey("Origin"); - Optional destinationField = sourcePassbook.getPrimaryFields().getPassFieldForKey("Des"); - Optional seatField = sourcePassbook.getAuxiliaryFields().getPassFieldForKey("SeatNumber"); - - if (originField.isPresent() && destinationField.isPresent()) { - prettifiedDescription = originField.get().value + "->" + destinationField.get().value; - if (seatField.isPresent()) { - prettifiedDescription += " @" + seatField.get().value; - } - } - } - } - - private void careForAirBerlin() { - if (sourcePassbook.getDescription().equals("boardcard")) { - final String flightRegex = "\\b\\w{1,3}\\d{3,4}\\b"; - - Optional flightField = sourcePassbook.getAuxiliaryFields().getPassFieldThatMatchesLabel(flightRegex); - - - if (!flightField.isPresent()) { - flightField = sourcePassbook.getHeaderFields().getPassFieldThatMatchesLabel(flightRegex); - } - - final Optional seatField = sourcePassbook.getAuxiliaryFields().getPassFieldForKey("seat"); - final Optional boardingGroupField = sourcePassbook.getSecondaryFields().getPassFieldForKey("boardingGroup"); - - if (flightField.isPresent() && seatField.isPresent() && boardingGroupField.isPresent()) { - prettifiedDescription = flightField.get().label + " " + flightField.get().value; - prettifiedDescription += " | " + seatField.get().label + " " + seatField.get().value; - prettifiedDescription += " | " + boardingGroupField.get().label + " " + boardingGroupField.get().value; - } // otherwise fallback to default - better save than sorry - } - } - - - public String getPrettyDescription() { - return prettifiedDescription; - } -} diff --git a/src/main/java/org/ligi/passandroid/model/QuirkCorrectingPassbook.java b/src/main/java/org/ligi/passandroid/model/QuirkCorrectingPassbook.java new file mode 100644 index 00000000..8150551c --- /dev/null +++ b/src/main/java/org/ligi/passandroid/model/QuirkCorrectingPassbook.java @@ -0,0 +1,71 @@ +package org.ligi.passandroid.model; + +import com.google.common.base.Optional; + +public abstract class QuirkCorrectingPassbook extends BasePassbook { + + public void correctQuirks() { + careForTUIFlight(); + careForAirBerlin(); + careForWestbahn(); + } + + private void careForWestbahn() { + if (!getRelevantDate().isPresent() && + getOrganisation().isPresent() && + getOrganisation().get().equals("WESTbahn") + ) { + + final Optional originField = getPrimaryFields().getPassFieldForKey("from"); + final Optional destinationField = getPrimaryFields().getPassFieldForKey("to"); + + description = "WESTbahn"; + + if (originField.isPresent()) { + description = originField.get().value; + } + + if (destinationField.isPresent()) { + description += "->" + destinationField.get().value; + } + } + } + + private void careForTUIFlight() { + if (getDescription().equals("TUIfly pass")) { + final Optional originField = getPrimaryFields().getPassFieldForKey("Origin"); + final Optional destinationField = getPrimaryFields().getPassFieldForKey("Des"); + final Optional seatField = getAuxiliaryFields().getPassFieldForKey("SeatNumber"); + + if (originField.isPresent() && destinationField.isPresent()) { + description = originField.get().value + "->" + destinationField.get().value; + if (seatField.isPresent()) { + description += " @" + seatField.get().value; + } + } + } + } + + + private void careForAirBerlin() { + if (getDescription().equals("boardcard")) { + final String flightRegex = "\\b\\w{1,3}\\d{3,4}\\b"; + + Optional flightField = getAuxiliaryFields().getPassFieldThatMatchesLabel(flightRegex); + + + if (!flightField.isPresent()) { + flightField = getHeaderFields().getPassFieldThatMatchesLabel(flightRegex); + } + + final Optional seatField = getAuxiliaryFields().getPassFieldForKey("seat"); + final Optional boardingGroupField = getSecondaryFields().getPassFieldForKey("boardingGroup"); + + if (flightField.isPresent() && seatField.isPresent() && boardingGroupField.isPresent()) { + description = flightField.get().label + " " + flightField.get().value; + description += " | " + seatField.get().label + " " + seatField.get().value; + description += " | " + boardingGroupField.get().label + " " + boardingGroupField.get().value; + } // otherwise fallback to default - better save than sorry + } + } +} diff --git a/src/main/java/org/ligi/passandroid/model/ReducedPassInformation.java b/src/main/java/org/ligi/passandroid/model/ReducedPassInformation.java index 1d0f0fb5..ca00901b 100644 --- a/src/main/java/org/ligi/passandroid/model/ReducedPassInformation.java +++ b/src/main/java/org/ligi/passandroid/model/ReducedPassInformation.java @@ -17,15 +17,13 @@ public class ReducedPassInformation implements Serializable { public ReducedPassInformation(Passbook pass) { - PrettifiedPassbookDecorator prettyPassBook = new PrettifiedPassbookDecorator(pass); - type = pass.getType(); - if (pass.hasRelevantDate()) { - relevantDate = pass.getRelevantDate(); + if (pass.getRelevantDate().isPresent()) { + relevantDate = pass.getRelevantDate().get(); } backgroundColor = pass.getBackGroundColor(); foregroundColor = pass.getForegroundColor(); - name = prettyPassBook.getPrettyDescription(); + name = pass.getDescription(); iconPath = pass.getIconPath(); id = pass.getId(); hasLocation = !pass.getLocations().isEmpty();