package co.smartreceipts.android.model.impl; import android.content.Context; import android.os.Parcel; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; import com.google.common.base.Preconditions; import java.io.File; import java.sql.Date; import java.util.TimeZone; import co.smartreceipts.android.R; import co.smartreceipts.android.model.Category; import co.smartreceipts.android.model.PaymentMethod; import co.smartreceipts.android.model.Price; import co.smartreceipts.android.model.Receipt; import co.smartreceipts.android.model.Source; import co.smartreceipts.android.model.Trip; import co.smartreceipts.android.model.utils.ModelUtils; import co.smartreceipts.android.persistence.DatabaseHelper; import co.smartreceipts.android.sync.model.SyncState; import co.smartreceipts.android.sync.model.impl.DefaultSyncState; import wb.android.storage.StorageManager; /** * A mostly immutable implementation of the {@link co.smartreceipts.android.model.Receipt} interface that * serves as the default implementation. */ public final class DefaultReceiptImpl implements Receipt { private final int mId; private final Trip mTrip; private final PaymentMethod mPaymentMethod; private final int mIndex; // Tracks the index in the list (if specified) private final String mName; private final String mComment; private final Category mCategory; private final Price mPrice, mTax; private final Date mDate; private final TimeZone mTimeZone; private final boolean mIsReimbursable; private final boolean mIsFullPage; private final Source mSource; private final String mExtraEditText1; private final String mExtraEditText2; private final String mExtraEditText3; private final SyncState mSyncState; private boolean mIsSelected; private File mFile; private long mFileLastModifiedTime; public DefaultReceiptImpl(int id, int index, @NonNull Trip trip, @Nullable File file, @Nullable PaymentMethod paymentMethod, @NonNull String name, @NonNull Category category, @NonNull String comment, @NonNull Price price, @NonNull Price tax, @NonNull Date date, @NonNull TimeZone timeZone, boolean isReimbursable, boolean isFullPage, boolean isSelected, @NonNull Source source, @Nullable String extraEditText1, @Nullable String extraEditText2, @Nullable String extraEditText3) { this(id, index, trip, file, paymentMethod, name, category, comment, price, tax, date, timeZone, isReimbursable, isFullPage, isSelected, source, extraEditText1, extraEditText2, extraEditText3, new DefaultSyncState()); } public DefaultReceiptImpl(int id, int index, @NonNull Trip trip, @Nullable File file, @Nullable PaymentMethod paymentMethod, @NonNull String name, @NonNull Category category, @NonNull String comment, @NonNull Price price, @NonNull Price tax, @NonNull Date date, @NonNull TimeZone timeZone, boolean isReimbursable, boolean isFullPage, boolean isSelected, @NonNull Source source, @Nullable String extraEditText1, @Nullable String extraEditText2, @Nullable String extraEditText3, @NonNull SyncState syncState) { mTrip = Preconditions.checkNotNull(trip); mName = Preconditions.checkNotNull(name); mCategory = Preconditions.checkNotNull(category); mComment = Preconditions.checkNotNull(comment); mSource = Preconditions.checkNotNull(source); mPrice = Preconditions.checkNotNull(price); mTax = Preconditions.checkNotNull(tax); mDate = Preconditions.checkNotNull(date); mTimeZone = Preconditions.checkNotNull(timeZone); mSyncState = Preconditions.checkNotNull(syncState); mId = id; mIndex = index; mFile = file; mFileLastModifiedTime = file != null ? file.lastModified() : -1; mPaymentMethod = paymentMethod; mIsReimbursable = isReimbursable; mIsFullPage = isFullPage; mExtraEditText1 = extraEditText1; mExtraEditText2 = extraEditText2; mExtraEditText3 = extraEditText3; mIsSelected = isSelected; } private DefaultReceiptImpl(@NonNull Parcel in) { mTrip = in.readParcelable(Trip.class.getClassLoader()); mPaymentMethod = in.readParcelable(PaymentMethod.class.getClassLoader()); mId = in.readInt(); mName = in.readString(); mCategory = in.readParcelable(Category.class.getClassLoader()); mComment = in.readString(); mPrice = in.readParcelable(Price.class.getClassLoader()); mTax = in.readParcelable(Price.class.getClassLoader()); final String fileName = in.readString(); mFile = TextUtils.isEmpty(fileName) ? null : new File(fileName); mFileLastModifiedTime = in.readLong(); mDate = new Date(in.readLong()); mIsReimbursable = (in.readByte() != 0); mIsFullPage = (in.readByte() != 0); mIsSelected = (in.readByte() != 0); mExtraEditText1 = in.readString(); mExtraEditText2 = in.readString(); mExtraEditText3 = in.readString(); mIndex = in.readInt(); mTimeZone = TimeZone.getTimeZone(in.readString()); mSyncState = in.readParcelable(SyncState.class.getClassLoader()); mSource = Source.Parcel; } @Override public int getId() { return mId; } @NonNull @Override public Trip getTrip() { return mTrip; } @Nullable @Override public PaymentMethod getPaymentMethod() { return mPaymentMethod; } @NonNull @Override public String getName() { return mName; } @Override public boolean hasFile() { return (mFile != null && mFile.exists()); } @Override public boolean hasImage() { if (mFile != null && mFile.exists()) { final String extension = StorageManager.getExtension(mFile); if (extension != null && (extension.equalsIgnoreCase("jpg") || extension.equalsIgnoreCase("jpeg") || extension .equalsIgnoreCase("png"))) { return true; } else { return false; } } else { return false; } } @Override public boolean hasPDF() { if (mFile != null && mFile.exists()) { final String extension = StorageManager.getExtension(mFile); if (extension != null && extension.equalsIgnoreCase("pdf")) { return true; } else { return false; } } else { return false; } } @NonNull @Override public String getMarkerAsString(@NonNull Context context) { if (hasImage()) { return context.getString(R.string.image); } else if (hasPDF()) { return context.getString(R.string.pdf); } else { return ""; } } @Nullable @Override public File getImage() { return mFile; } @Nullable @Override public File getPDF() { return mFile; } @Nullable @Override public File getFile() { return mFile; } @NonNull @Override public String getFilePath() { if (hasFile()) { return mFile.getAbsolutePath(); } else { return ""; } } @NonNull @Override public String getFileName() { if (hasFile()) { return mFile.getName(); } else { return ""; } } @Override public long getFileLastModifiedTime() { return mFileLastModifiedTime; } @Override public void setFile(File file) { mFile = file; mFileLastModifiedTime = file != null ? file.lastModified() : -1; } @NonNull @Override public Source getSource() { return mSource; } @NonNull @Override public Category getCategory() { return mCategory; } @NonNull @Override public String getComment() { return mComment; } @NonNull @Override public Price getPrice() { return mPrice; } @NonNull @Override public Price getTax() { return mTax; } @NonNull @Override public Date getDate() { return mDate; } @NonNull @Override public String getFormattedDate(@NonNull Context context, @NonNull String separator) { return ModelUtils.getFormattedDate(mDate, (mTimeZone != null) ? mTimeZone : TimeZone.getDefault(), context, separator); } @NonNull @Override public TimeZone getTimeZone() { return (mTimeZone != null) ? mTimeZone : TimeZone.getDefault(); } @Override public boolean isReimbursable() { return mIsReimbursable; } @Override public boolean isFullPage() { return mIsFullPage; } @Override public boolean isSelected() { return mIsSelected; } @Override public int getIndex() { return mIndex; } @Nullable @Override public String getExtraEditText1() { if (DatabaseHelper.NO_DATA.equals(mExtraEditText1)) { return null; } else { return mExtraEditText1; } } @Nullable @Override public String getExtraEditText2() { if (DatabaseHelper.NO_DATA.equals(mExtraEditText2)) { return null; } else { return mExtraEditText2; } } @Nullable @Override public String getExtraEditText3() { if (DatabaseHelper.NO_DATA.equals(mExtraEditText3)) { return null; } else { return mExtraEditText3; } } @Override public boolean hasExtraEditText1() { return (mExtraEditText1 != null) && !mExtraEditText1.equals(DatabaseHelper.NO_DATA); } @Override public boolean hasExtraEditText2() { return (mExtraEditText2 != null) && !mExtraEditText2.equals(DatabaseHelper.NO_DATA); } @Override public boolean hasExtraEditText3() { return (mExtraEditText3 != null)&& !mExtraEditText3.equals(DatabaseHelper.NO_DATA); } @NonNull @Override public SyncState getSyncState() { return mSyncState; } @Override public String toString() { return "DefaultReceiptImpl{" + "mId=" + mId + ", mName='" + mName + '\'' + ", trip=" + mTrip.getName() + ", mPaymentMethod=" + mPaymentMethod + ", mIndex=" + mIndex + ", mComment='" + mComment + '\'' + ", mCategory=" + mCategory + ", mPrice=" + mPrice.getCurrencyFormattedPrice() + ", mTax=" + mTax + ", mDate=" + mDate + ", mTimeZone=" + mTimeZone + ", mIsReimbursable=" + mIsReimbursable + ", mIsFullPage=" + mIsFullPage + ", mSource=" + mSource + ", mExtraEditText1='" + mExtraEditText1 + '\'' + ", mExtraEditText2='" + mExtraEditText2 + '\'' + ", mExtraEditText3='" + mExtraEditText3 + '\'' + ", mIsSelected=" + mIsSelected + ", mFile=" + mFile + ", mFileLastModifiedTime=" + mFileLastModifiedTime + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof DefaultReceiptImpl)) return false; DefaultReceiptImpl that = (DefaultReceiptImpl) o; if (mId != that.mId) return false; if (mIsReimbursable != that.mIsReimbursable) return false; if (mIsFullPage != that.mIsFullPage) return false; if (!mTrip.equals(that.mTrip)) return false; if (mPaymentMethod != null ? !mPaymentMethod.equals(that.mPaymentMethod) : that.mPaymentMethod != null) return false; if (!mName.equals(that.mName)) return false; if (!mComment.equals(that.mComment)) return false; if (!mCategory.equals(that.mCategory)) return false; if (!mPrice.equals(that.mPrice)) return false; if (!mTax.equals(that.mTax)) return false; if (!mDate.equals(that.mDate)) return false; if (!mTimeZone.equals(that.mTimeZone)) return false; if (mExtraEditText1 != null ? !mExtraEditText1.equals(that.mExtraEditText1) : that.mExtraEditText1 != null) return false; if (mExtraEditText2 != null ? !mExtraEditText2.equals(that.mExtraEditText2) : that.mExtraEditText2 != null) return false; if (mExtraEditText3 != null ? !mExtraEditText3.equals(that.mExtraEditText3) : that.mExtraEditText3 != null) return false; if (mFileLastModifiedTime != that.mFileLastModifiedTime) return false; return mFile != null ? mFile.equals(that.mFile) : that.mFile == null; } @Override public int hashCode() { int result = mId; result = 31 * result + mTrip.hashCode(); result = 31 * result + (mPaymentMethod != null ? mPaymentMethod.hashCode() : 0); result = 31 * result + mName.hashCode(); result = 31 * result + mComment.hashCode(); result = 31 * result + mCategory.hashCode(); result = 31 * result + mPrice.hashCode(); result = 31 * result + mTax.hashCode(); result = 31 * result + mDate.hashCode(); result = 31 * result + mTimeZone.hashCode(); result = 31 * result + (mIsReimbursable ? 1 : 0); result = 31 * result + (mIsFullPage ? 1 : 0); result = 31 * result + (mExtraEditText1 != null ? mExtraEditText1.hashCode() : 0); result = 31 * result + (mExtraEditText2 != null ? mExtraEditText2.hashCode() : 0); result = 31 * result + (mExtraEditText3 != null ? mExtraEditText3.hashCode() : 0); result = 31 * result + (mFile != null ? mFile.hashCode() : 0); result = 31 * result + (int) mFileLastModifiedTime; return result; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeParcelable(getTrip(), flags); dest.writeParcelable(getPaymentMethod(), flags); dest.writeInt(getId()); dest.writeString(getName()); dest.writeParcelable(getCategory(), flags); dest.writeString(getComment()); dest.writeParcelable(getPrice(), flags); dest.writeParcelable(getTax(), flags); dest.writeString(getFilePath()); dest.writeLong(getFileLastModifiedTime()); dest.writeLong(getDate().getTime()); dest.writeByte((byte) (isReimbursable() ? 1 : 0)); dest.writeByte((byte) (isFullPage() ? 1 : 0)); dest.writeByte((byte) (isSelected() ? 1 : 0)); dest.writeString(getExtraEditText1()); dest.writeString(getExtraEditText2()); dest.writeString(getExtraEditText3()); dest.writeInt(getIndex()); dest.writeString(mTimeZone.getID()); dest.writeParcelable(getSyncState(), flags); } public static Creator<DefaultReceiptImpl> CREATOR = new Creator<DefaultReceiptImpl>() { @Override public DefaultReceiptImpl createFromParcel(Parcel source) { return new DefaultReceiptImpl(source); } @Override public DefaultReceiptImpl[] newArray(int size) { return new DefaultReceiptImpl[size]; } }; @Override public int compareTo(@NonNull Receipt receipt) { return receipt.getDate().compareTo(mDate); } }