package de.fau.cs.mad.fablab.android.model; import com.j256.ormlite.dao.RuntimeExceptionDao; import com.j256.ormlite.stmt.QueryBuilder; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; import de.fau.cs.mad.fablab.android.viewmodel.common.ObservableArrayList; import de.fau.cs.mad.fablab.rest.core.News; import de.fau.cs.mad.fablab.rest.myapi.NewsApi; import retrofit.Callback; import retrofit.RetrofitError; import retrofit.client.Response; /** * Handles the connection to the rest server to receive news. * Stores the results and fires events on success. */ public class NewsModel { private static final int ELEMENT_COUNT = 10; private ObservableArrayList<News> mNews; private NewsApi mNewsApi; private boolean mNewsRequested; private RuntimeExceptionDao<News, Long> mNewsDao; private long mTimeStampLastUpdate; private Date mDateLastDisplayedNews; private boolean mEndReached; private Callback<List<News>> mNewsApiCallback = new Callback<List<News>>() { @Override public void success(List<News> news, Response response) { mNews.addAll(news); mNewsRequested = false; for(News n : news) { createIfNotExists(mNewsDao, n); } mDateLastDisplayedNews = mNews.get(mNews.size()-1).getPubDate(); } @Override public void failure(RetrofitError error) { mNewsRequested = false; if(error.getMessage().equals("404 Not Found")) { mEndReached = true; } } }; private Callback<List<News>> mNewsApiCallbackUpdate = new Callback<List<News>>() { @Override public void success(List<News> news, Response response) { mNewsRequested = false; for(News n : news) { createIfNotExists(mNewsDao, n); } mNews.clear(); mDateLastDisplayedNews = new Date(System.currentTimeMillis()); mEndReached = false; fetchNextNews(); mTimeStampLastUpdate = System.currentTimeMillis(); } @Override public void failure(RetrofitError error) { mNewsRequested = false; } }; public NewsModel(NewsApi newsApi, RuntimeExceptionDao<News, Long> newsDao) { mNewsApi = newsApi; mNewsDao = newsDao; mNews = new ObservableArrayList<>(); mNewsRequested = false; mTimeStampLastUpdate = 0; mDateLastDisplayedNews = new Date(System.currentTimeMillis()); mEndReached = false; fetchNextNews(); } public void fetchNextNews() { //check whether to get news from database or server if (!mNewsRequested && mNews.size() + ELEMENT_COUNT > mNewsDao.countOf() && !mEndReached) { mNewsRequested = true; mNewsApi.find(mNews.size(), ELEMENT_COUNT, mNewsApiCallback); } else if (!mNewsRequested && !mEndReached) { mNewsRequested = true; List<News> fetchedNews = new ArrayList<>(); //get next Element_count elements from database QueryBuilder<News, Long> queryBuilder = mNewsDao.queryBuilder(); //sort elements in descending order according to pubdate and only return //ELEMENT_COUNT news queryBuilder.orderBy("pubDate", false).limit(ELEMENT_COUNT); try { queryBuilder.where().lt("pubDate", mDateLastDisplayedNews); fetchedNews = mNewsDao.query(queryBuilder.prepare()); } catch (SQLException e) { e.printStackTrace(); } mNews.addAll(fetchedNews); mDateLastDisplayedNews = mNews.get(mNews.size()-1).getPubDate(); mNewsRequested = false; } } public ObservableArrayList<News> getNews() { return mNews; } public void checkForUpdates() { mNewsApi.findNewsSince(mTimeStampLastUpdate, mNewsApiCallbackUpdate); } private void createIfNotExists(RuntimeExceptionDao<News, Long> newsDao, News news) { List<News> retrievedNews = newsDao.queryForEq("title", news.getTitle()); if(retrievedNews.size() == 0) { newsDao.create(news); } } }