refactor Passbook and care for Westbahn

This commit is contained in:
ligi 2014-06-23 21:25:31 +02:00
parent 08e21c10f6
commit d7d12519fd
6 changed files with 208 additions and 140 deletions

View file

@ -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<String> 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<DateTime> relevantDate = Optional.absent();
protected Optional<DateTime> expirationDate = Optional.absent();
protected PassFieldList primaryFields, secondaryFields, backFields, auxiliaryFields, headerFields;
protected List<PassLocation> locations = new ArrayList<>();
@Override
public Optional<String> getOrganisation() {
return organisation;
}
@Override
public int getForegroundColor() {
return foregroundColor;
}
@Override
public Optional<DateTime> getRelevantDate() {
return relevantDate;
}
@Override
public Optional<DateTime> 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<PassLocation> getLocations() {
return locations;
}
}

View file

@ -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<PassLocation> locations = new ArrayList<PassLocation>();
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<PassLocation> 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;
}
}

View file

@ -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<DateTime> getRelevantDate();
DateTime getRelevantDate();
Optional<DateTime> getExpirationDate();
String getId();
String getPlainJsonString();
Optional<String> getOrganisation();
}

View file

@ -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<PassField> originField = sourcePassbook.getPrimaryFields().getPassFieldForKey("Origin");
Optional<PassField> destinationField = sourcePassbook.getPrimaryFields().getPassFieldForKey("Des");
Optional<PassField> 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<PassField> flightField = sourcePassbook.getAuxiliaryFields().getPassFieldThatMatchesLabel(flightRegex);
if (!flightField.isPresent()) {
flightField = sourcePassbook.getHeaderFields().getPassFieldThatMatchesLabel(flightRegex);
}
final Optional<PassField> seatField = sourcePassbook.getAuxiliaryFields().getPassFieldForKey("seat");
final Optional<PassField> 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;
}
}

View file

@ -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<PassField> originField = getPrimaryFields().getPassFieldForKey("from");
final Optional<PassField> 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<PassField> originField = getPrimaryFields().getPassFieldForKey("Origin");
final Optional<PassField> destinationField = getPrimaryFields().getPassFieldForKey("Des");
final Optional<PassField> 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<PassField> flightField = getAuxiliaryFields().getPassFieldThatMatchesLabel(flightRegex);
if (!flightField.isPresent()) {
flightField = getHeaderFields().getPassFieldThatMatchesLabel(flightRegex);
}
final Optional<PassField> seatField = getAuxiliaryFields().getPassFieldForKey("seat");
final Optional<PassField> 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
}
}
}

View file

@ -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();