package com.qubling.sidekick.search; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import com.qubling.sidekick.fetch.Fetcher; import com.qubling.sidekick.fetch.LimitedFetcher; import com.qubling.sidekick.fetch.UpdateFetcher; import com.qubling.sidekick.instance.Instance; import com.qubling.sidekick.job.JobExecutor; import com.qubling.sidekick.job.JobMonitor; import com.qubling.sidekick.job.Job; import android.app.Activity; public class Search<SomeInstance extends Instance<SomeInstance>> implements JobMonitor { public interface OnSearchActivity { public void onSearchStart(); public void onSearchComplete(); } private static class Plan extends ArrayList<Job> { private static final long serialVersionUID = -8139612794037092258L; } private final Activity activity; private final Fetcher<SomeInstance> originalFetcher; private final Search.Plan searchPlan; private final Fetcher.OnFinished<SomeInstance> finishListener; private final Collection<OnSearchActivity> activityListeners; private Runnable makeFollowup(final Fetcher<SomeInstance> fetcher) { if (finishListener == null) return null; return new Runnable() { @Override public void run() { finishListener.onFinishedFetch(fetcher, originalFetcher.getResultSet()); } @Override public String toString() { return "Followup " + finishListener; } }; } public Search(Activity activity, Fetcher<SomeInstance> fetcher, Fetcher.OnFinished<SomeInstance> listener) { finishListener = listener; this.activity = activity; this.searchPlan = new Search.Plan(); Job originalJob = Job.newJob(activity); originalJob.addCommand(fetcher, makeFollowup(fetcher)); this.searchPlan.add(originalJob); this.originalFetcher = fetcher; this.activityListeners = new HashSet<Search.OnSearchActivity>(); } public Search<SomeInstance> thenDoFetch(UpdateFetcher<SomeInstance>... fetchersArray) { Job fetcherJob = Job.newJob(activity); for (UpdateFetcher<SomeInstance> fetcher : fetchersArray) { // Log.d("Search", "originalFetcher.getResultSet() " + originalFetcher + " " + originalFetcher.getResultSet()); fetcher.setIncomingResultSet( new ResultsForUpdate<SomeInstance>(fetcher, originalFetcher.getResultSet())); fetcherJob.addCommand(fetcher, makeFollowup(fetcher)); } searchPlan.add(fetcherJob); return this; } public Search<SomeInstance> whenFinishedRun(Runnable... runnablesArray) { Job commandJob = Job.newJob(activity); for (Runnable runnable : runnablesArray) { commandJob.addCommand(runnable); } searchPlan.add(commandJob); return this; } public Search<SomeInstance> start() { executeJobsStarted(); JobExecutor executor = new JobExecutor(activity); for (Job job : searchPlan) { executor.addCommand(job); } Runnable[] finalCommands = new Runnable[1]; finalCommands[0] = new Runnable() { @Override public void run() { executeJobsComplete(); } @Override public String toString() { return "Notify executeJobsComplete()"; } }; executor.execute(finalCommands); return this; } public Search<SomeInstance> fetchMore() { if (originalFetcher instanceof LimitedFetcher<?>) { LimitedFetcher<?> limitFetcher = (LimitedFetcher<?>) originalFetcher; ResultSet<SomeInstance> results = originalFetcher.getResultSet(); if (results.getTotalSize() > limitFetcher.getSize()) { limitFetcher.setFrom(limitFetcher.getSize()); } } return start(); } public ResultSet<SomeInstance> getResultSet() { return originalFetcher.getResultSet(); } public void addOnSearchActivityListener(OnSearchActivity listener) { activityListeners.add(listener); } public void removeOnSearchActivityListener(OnSearchActivity listener) { activityListeners.remove(listener); } @Override public void executeJobsStarted() { // Log.d("Search", "notifyOnSearchStart()"); for (OnSearchActivity listener : activityListeners) { listener.onSearchStart(); } } @Override public void executeJobsComplete() { // Log.d("Search", "notifyOnSearchComplete()"); for (OnSearchActivity listener : activityListeners) { listener.onSearchComplete(); } } }