package org.mtransit.android.task; import java.util.ArrayList; import java.util.HashSet; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.mtransit.android.commons.CollectionUtils; import org.mtransit.android.commons.MTLog; import org.mtransit.android.commons.RuntimeUtils; import org.mtransit.android.commons.data.News; import org.mtransit.android.commons.provider.NewsProviderContract; import org.mtransit.android.commons.provider.NewsProviderContract.Filter; import org.mtransit.android.commons.task.MTCallable; import org.mtransit.android.data.DataSourceManager; import org.mtransit.android.data.DataSourceProvider; import org.mtransit.android.data.NewsProviderProperties; import android.content.Context; public class NewsLoader extends MTAsyncTaskLoaderV4<ArrayList<News>> { private static final String TAG = NewsLoader.class.getSimpleName(); @Override public String getLogTag() { return TAG; } private ArrayList<News> news; private ArrayList<String> targetAuthorities; private ArrayList<String> filterUUIDs; private ArrayList<String> filterTargets; public NewsLoader(Context context, ArrayList<String> optTargetAuthorities, ArrayList<String> optFilterUUIDs, ArrayList<String> optFilterTargets) { super(context); this.targetAuthorities = optTargetAuthorities; this.filterUUIDs = optFilterUUIDs; this.filterTargets = optFilterTargets; } @Override public ArrayList<News> loadInBackgroundMT() { if (this.news != null) { return this.news; } this.news = new ArrayList<News>(); ArrayList<NewsProviderProperties> newsProviders; if (CollectionUtils.getSize(this.targetAuthorities) == 0) { newsProviders = DataSourceProvider.get(getContext()).getAllNewsProvider(); } else { newsProviders = new ArrayList<NewsProviderProperties>(); for (String targetAuthority : this.targetAuthorities) { newsProviders.addAll(DataSourceProvider.get(getContext()).getTargetAuthorityNewsProviders(targetAuthority)); } } if (CollectionUtils.getSize(newsProviders) == 0) { MTLog.w(this, "loadInBackground() > no News provider found"); return this.news; } ThreadPoolExecutor executor = new ThreadPoolExecutor(RuntimeUtils.NUMBER_OF_CORES, RuntimeUtils.NUMBER_OF_CORES, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(newsProviders.size())); ArrayList<Future<ArrayList<News>>> taskList = new ArrayList<Future<ArrayList<News>>>(); for (NewsProviderProperties newsProvider : newsProviders) { taskList.add(executor.submit(new FindNewsTask(getContext(), newsProvider.getAuthority(), this.filterUUIDs, this.filterTargets))); } HashSet<String> newsUUIDs = new HashSet<String>(); for (Future<ArrayList<News>> future : taskList) { try { ArrayList<News> agencyNews = future.get(); for (News aNews : agencyNews) { if (newsUUIDs.contains(aNews.getUUID())) { continue; } this.news.add(aNews); newsUUIDs.add(aNews.getUUID()); } } catch (Exception e) { MTLog.w(this, e, "Error while loading in background!"); } } executor.shutdown(); CollectionUtils.sort(this.news, News.NEWS_COMPARATOR); return this.news; } @Override protected void onStartLoading() { super.onStartLoading(); if (this.news != null) { deliverResult(this.news); } if (this.news == null) { forceLoad(); } } @Override protected void onStopLoading() { super.onStopLoading(); cancelLoad(); } @Override public void deliverResult(ArrayList<News> data) { this.news = data; if (isStarted()) { super.deliverResult(data); } } private static class FindNewsTask extends MTCallable<ArrayList<News>> { private static final String TAG = NewsLoader.class.getSimpleName() + ">" + FindNewsTask.class.getSimpleName(); @Override public String getLogTag() { return TAG; } private Context context; private String authority; private ArrayList<String> filterUUIDs; private ArrayList<String> filterTargets; public FindNewsTask(Context context, String authority, ArrayList<String> optFilterUUIDs, ArrayList<String> optFilterTargets) { this.context = context; this.authority = authority; this.filterUUIDs = optFilterUUIDs; this.filterTargets = optFilterTargets; } @Override public ArrayList<News> callMT() throws Exception { Filter newsFilter; if (CollectionUtils.getSize(this.filterUUIDs) > 0) { newsFilter = NewsProviderContract.Filter.getNewUUIDsFilter(this.filterUUIDs); } else if (CollectionUtils.getSize(this.filterTargets) > 0) { newsFilter = NewsProviderContract.Filter.getNewTargetsFilter(this.filterTargets); } else { newsFilter = NewsProviderContract.Filter.getNewEmptyFilter(); } return DataSourceManager.findNews(this.context, this.authority, newsFilter); } } }