/* * Copyright 2015 Hannes Dorfmann. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hannesdorfmann.mosby3.sample.mail.model.mail; import com.hannesdorfmann.mosby3.sample.mail.R; import com.hannesdorfmann.mosby3.sample.mail.model.account.AccountManager; import com.hannesdorfmann.mosby3.sample.mail.model.account.NotAuthenticatedException; import com.hannesdorfmann.mosby3.sample.mail.model.mail.statistics.MailStatistics; import com.hannesdorfmann.mosby3.sample.mail.model.mail.statistics.MailsCount; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import rx.Observable; import rx.functions.Action2; import rx.functions.Func0; import rx.functions.Func1; /** * @author Hannes Dorfmann */ public class MailProvider { public static int DELAY = 2000; public static int authExceptionEach = 15; public static int errorEach = 5; private int counter = 0; private AtomicInteger lastId; private AccountManager accountManager; private List<Mail> mails; public static final Label INBOX_LABEL = new Label(Label.INBOX, R.drawable.ic_inbox, 0); private Label sentLabel = new Label(Label.SENT, R.drawable.ic_send, 0); private Label spamLabel = new Label(Label.SPAM, R.drawable.ic_spam, 0); private Label trashLabel = new Label(Label.TRASH, R.drawable.ic_delete, 0); public MailProvider(AccountManager accountManager, MailGenerator genrator) { this.accountManager = accountManager; mails = genrator.generateMails(); lastId = new AtomicInteger(mails.get(mails.size() - 1).getId()); } /** * Get the labels with the number of unread mails. */ public Observable<List<Label>> getLabels() { return Observable.just(mails).flatMap(new Func1<List<Mail>, Observable<List<Label>>>() { @Override public Observable<List<Label>> call(List<Mail> mails) { delay(); Observable error = checkExceptions(); if (error != null) { return error; } List<Label> labels = new ArrayList<>(4); labels.add(INBOX_LABEL); labels.add(sentLabel); labels.add(spamLabel); labels.add(trashLabel); int inbox = 0; int spam = 0; int sent = 0; int trash = 0; for (Mail m : mails) { if (m.isRead()) { continue; } switch (m.getLabel()) { case Label.INBOX: inbox++; break; case Label.SENT: sent++; break; case Label.SPAM: spam++; break; case Label.TRASH: trash++; break; } } INBOX_LABEL.setUnreadCount(inbox); sentLabel.setUnreadCount(sent); spamLabel.setUnreadCount(spam); trashLabel.setUnreadCount(trash); return Observable.just(labels); } }); } public Observable<Mail> getMail(final int id) { return getFilteredMailList(new Func1<Mail, Boolean>() { @Override public Boolean call(Mail mail) { return mail.getId() == id; } }).flatMap(new Func1<List<Mail>, Observable<Mail>>() { @Override public Observable<Mail> call(List<Mail> mails) { if (mails == null || mails.isEmpty()) { return Observable.error(new NotFoundException()); } return Observable.just(mails.get(0)); } }); } /** * Get a list of mails with the given label */ public Observable<List<Mail>> getMailsOfLabel(final String l) { return getFilteredMailList(new Func1<Mail, Boolean>() { @Override public Boolean call(Mail mail) { return mail.getLabel().equals(l); } }); } public Observable<Mail> markAsRead(final Mail mail, final boolean read) { mail.read(read); final int id = mail.getId(); return getFilteredMailList(new Func1<Mail, Boolean>() { @Override public Boolean call(Mail mail) { return mail.getId() == id; } }, false).flatMap(new Func1<List<Mail>, Observable<Mail>>() { @Override public Observable<Mail> call(List<Mail> mails) { if (mails == null || mails.isEmpty()) { return Observable.error(new NotFoundException()); } Mail toChange = mails.get(0); toChange.read(read); return Observable.just(toChange); } }); } /** * Star or unstar a mail * * @param mailId the id of the mail * @param star true, if you want to star, false if you want to unstar */ public Observable<Mail> starMail(int mailId, final boolean star) { return getMail(mailId).map(new Func1<Mail, Mail>() { @Override public Mail call(Mail mail) { mail.setStarred(star); return mail; } }); } /** * Creates and saves a new mail */ public Observable<Mail> addMailWithDelay(final Mail mail) { return Observable.defer(new Func0<Observable<Mail>>() { @Override public Observable<Mail> call() { delay(); Observable o = checkExceptions(); if (o != null) { return o; } return Observable.just(mail); } }).flatMap(new Func1<Mail, Observable<Mail>>() { @Override public Observable<Mail> call(Mail mail) { return addMail(mail); } }); } public Observable<Mail> addMail(final Mail mail) { return Observable.defer(new Func0<Observable<Mail>>() { @Override public Observable<Mail> call() { mail.id(lastId.incrementAndGet()); mails.add(mail); return Observable.just(mail); } }); } public Observable<Mail> setLabel(Mail mail, final String label) { mail.label(label); return setLabel(mail.getId(), label); } public Observable<Mail> setLabel(int mailId, final String label) { return getMail(mailId).map(new Func1<Mail, Mail>() { @Override public Mail call(Mail mail) { mail.label(label); return mail; } }); } public Observable<List<Mail>> searchForMails(String query, final int limit) { return searchForOlderMails(query, new Date(), limit); } public Observable<List<Mail>> searchForOlderMails(final String query, final Date olderAs, final int limit) { return getFilteredMailList(new Func1<Mail, Boolean>() { @Override public Boolean call(Mail mail) { boolean senderCheck = mail.getSender() != null ? mail.getSender().getEmail().contains(query) : false; boolean receiverCheck = mail.getReceiver() != null ? mail.getReceiver().getEmail().contains(query) : false; return mail.getDate().before(olderAs) && (mail.getSubject().contains(query) || mail.getText().contains(query) || senderCheck || receiverCheck); } }).map(new Func1<List<Mail>, List<Mail>>() { @Override public List<Mail> call(List<Mail> mails) { if (mails.size() <= limit) { return mails; } return mails.subList(0, limit); } }); } private Observable<List<Mail>> getFilteredMailList(Func1<Mail, Boolean> filterFnc) { return getFilteredMailList(filterFnc, true); } public Observable<List<Mail>> getMailsSentBy(final int personId) { return getFilteredMailList(new Func1<Mail, Boolean>() { @Override public Boolean call(Mail mail) { return mail.getSender().getId() == personId; } }); } public Observable<MailStatistics> getStatistics() { return Observable.defer(new Func0<Observable<MailStatistics>>() { @Override public Observable<MailStatistics> call() { delay(); Observable o = checkExceptions(); if (o != null) { return o; } Map<String, MailsCount> mailsCountMap = new HashMap<String, MailsCount>(); for (Mail m : mails) { MailsCount count = mailsCountMap.get(m.getLabel()); if (count == null) { count = new MailsCount(m.getLabel(), 0); mailsCountMap.put(m.getLabel(), count); } count.incrementCount(); } return Observable.just( new MailStatistics(new ArrayList<MailsCount>(mailsCountMap.values()))); } }); } /** * Filters the list of mails by the given criteria */ private Observable<List<Mail>> getFilteredMailList(Func1<Mail, Boolean> filterFnc, final boolean withDelayAndError) { return Observable.defer(new Func0<Observable<Mail>>() { @Override public Observable<Mail> call() { if (withDelayAndError) { delay(); Observable o = checkExceptions(); if (o != null) { return o; } } return Observable.from(mails); } }).filter(filterFnc).collect(new Func0<List<Mail>>() { @Override public List<Mail> call() { return new ArrayList<Mail>(); } }, new Action2<List<Mail>, Mail>() { @Override public void call(List<Mail> mails, Mail mail) { mails.add(mail); } }).map(new Func1<List<Mail>, List<Mail>>() { @Override public List<Mail> call(List<Mail> mails) { Collections.sort(mails, MailComparator.INSTANCE); return mails; } }); } private void delay() { if (DELAY > 0) { try { Thread.sleep(DELAY); } catch (InterruptedException e) { // e.printStackTrace(); } } } private Observable checkExceptions() { counter++; if (authExceptionEach > 0 && (!accountManager.isUserAuthenticated() || counter % authExceptionEach == 0)) { return Observable.error(new NotAuthenticatedException()); } if (errorEach > 0 && counter % errorEach == 0) { return Observable.error(new Exception("Fake Excption")); } return null; } int getLastMailId() { return lastId.get(); } }