package com.qubling.sidekick.job; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.RejectedExecutionException; import android.app.Activity; import android.os.Build; import android.util.Log; public abstract class Job implements Runnable { private Collection<Runnable> commands; private final Activity activity; protected Job(Activity activity) { this.activity = activity; this.commands = new ArrayList<Runnable>(); } public static Job newJob(Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { return new JobEclair(activity); } else { return new JobHoneycomb(activity); } } public void addCommand(Runnable command) { addCommand(command, null); } public void addCommand(final Runnable command, final Runnable followup) { if (followup != null) { commands.add(new Runnable() { @Override public void run() { command.run(); activity.runOnUiThread(followup); } @Override public String toString() { return "Runnable " + command + " Followed By " + followup; } }); } else { commands.add(command); } } @Override public void run() { LinkedList<Runnable> commandsCopy = new LinkedList<Runnable>(commands); final CountDownLatch latch = new CountDownLatch(commandsCopy.size()); while (!commandsCopy.isEmpty()) { final Runnable command = commandsCopy.poll(); JobExecutor job = new JobExecutor(activity); job.addCommand(new Runnable() { @Override public void run() { command.run(); latch.countDown(); } @Override public String toString() { return "Latched " + command; } }); try { executeJob(job); } catch (RejectedExecutionException e) { Log.e("Job", "Failed to start job in parallel, will try again.", e); commandsCopy.offer(command); } } try { latch.await(); } catch (InterruptedException e) { Log.e("Job", "Interrupted while waiting for jobs to finish.", e); } } public abstract void executeJob(JobExecutor job) throws RejectedExecutionException; @Override public String toString() { StringBuilder commandList = new StringBuilder(); for (Runnable command : commands) { commandList.append(command); commandList.append(","); } return "Job " + commandList; } }