package co.smartreceipts.android.ocr.util;
import android.support.annotation.Nullable;
import java.math.BigDecimal;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import co.smartreceipts.android.model.utils.ModelUtils;
import co.smartreceipts.android.ocr.apis.model.OcrResponse;
import co.smartreceipts.android.utils.log.Logger;
/**
* A simple utility class, which will allow us to handle all the {@code null} risks that we need to deal
* with when processing {@link OcrResponse}.
*/
public class OcrResponseParser {
/**
* Tt can be a major pain to control the UI to move our date forward (eg let's say it guesses 11-May-2012
* instead of 11-May-2017, then we have to move the calendar forward 5 years). As a result, we define this
* minimum confidence threshold level to ensure we only process the date when this level is met
*/
private static final double MINIMUM_DATE_CONFIDENCE = 0.5;
private final OcrResponse ocrResponse;
public OcrResponseParser(@Nullable OcrResponse ocrResponse) {
this.ocrResponse = ocrResponse;
}
/**
* @return the value of {@link OcrResponse#getMerchant()} as a {@link String} or {@code null} if it was not found
*/
@Nullable
public String getMerchant() {
if (ocrResponse != null && ocrResponse.getMerchant() != null && ocrResponse.getMerchant().getData() != null) {
return ocrResponse.getMerchant().getData();
} else {
return null;
}
}
/**
* @return the value of {@link OcrResponse#getTotalAmount()} ()} as a price {@link String} or {@code null} if it was not found
*/
@Nullable
public String getTotalAmount() {
if (ocrResponse != null && ocrResponse.getTotalAmount() != null && ocrResponse.getTotalAmount().getData() != null) {
return ModelUtils.getDecimalFormattedValue(new BigDecimal(ocrResponse.getTotalAmount().getData()));
} else {
return null;
}
}
/**
* @return the value of {@link OcrResponse#getTaxAmount()} ()} ()} as a price {@link String} or {@code null} if it was not found
*/
@Nullable
public String getTaxAmount() {
if (ocrResponse != null && ocrResponse.getTaxAmount() != null && ocrResponse.getTaxAmount().getData() != null) {
return ModelUtils.getDecimalFormattedValue(new BigDecimal(ocrResponse.getTaxAmount().getData()));
} else {
return null;
}
}
/**
* @return the value of {@link OcrResponse#getDate()} ()} ()} as a price {@link Date} or {@code null} if it was not found (or invalid)
*/
@Nullable
public Date getDate() {
if (ocrResponse != null && ocrResponse.getDate() != null && ocrResponse.getDate().getData() != null && ocrResponse.getDate().getConfidenceLevel() > MINIMUM_DATE_CONFIDENCE) {
try {
final SimpleDateFormat iso8601Formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
final GregorianCalendar ocrResponseCalendar = new GregorianCalendar();
ocrResponseCalendar.setTime(iso8601Formatter.parse(ocrResponse.getDate().getData()));
ocrResponseCalendar.set(Calendar.HOUR_OF_DAY, 0);
ocrResponseCalendar.set(Calendar.MINUTE, 0);
ocrResponseCalendar.set(Calendar.SECOND, 0);
ocrResponseCalendar.set(Calendar.MILLISECOND, 0);
// Shift this by the current time (local) for hours/mins/secs/m
final GregorianCalendar localTimeCalendar = new GregorianCalendar();
localTimeCalendar.setTime(new Date(System.currentTimeMillis()));
ocrResponseCalendar.add(Calendar.HOUR_OF_DAY, localTimeCalendar.get(Calendar.HOUR_OF_DAY));
ocrResponseCalendar.add(Calendar.MINUTE, localTimeCalendar.get(Calendar.MINUTE));
ocrResponseCalendar.add(Calendar.SECOND, localTimeCalendar.get(Calendar.SECOND));
ocrResponseCalendar.add(Calendar.MILLISECOND, localTimeCalendar.get(Calendar.MILLISECOND));
return new Date(ocrResponseCalendar.getTime().getTime());
} catch (ParseException e) {
Logger.error(this, "Failed to parse OCR Date.", e);
}
}
return null;
}
}