// Path: src/main/java/com/indeed/proctor/webapp/extensions/AfterBackgroundJobExecute.java
// public interface AfterBackgroundJobExecute {
//     <T> void afterExecute(final BackgroundJob<T> job, T result);
// }
// 
// Path: src/main/java/com/indeed/proctor/webapp/extensions/BeforeBackgroundJobExecute.java
// public interface BeforeBackgroundJobExecute {
//     <T> void beforeExecute(final BackgroundJob<T> job);
// }


import com.google.common.collect.Lists;
import com.indeed.proctor.webapp.extensions.AfterBackgroundJobExecute;
import com.indeed.proctor.webapp.extensions.BeforeBackgroundJobExecute;
import org.apache.log4j.Logger;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
package com.indeed.proctor.webapp.jobs;



/**
 */
public abstract class BackgroundJob<T> implements Callable<T> {
    private static final Logger LOGGER = Logger.getLogger(BackgroundJob.class);

    private Future<T> future;
    private JobStatus status = JobStatus.PENDING;
    protected final StringBuilder logBuilder = new StringBuilder();

    private Long id;
    private UUID uuid;

    private final long createdTime = System.currentTimeMillis();

    // URL to direct users to upon completion
    private final List<ResultUrl> urls = Lists.newArrayList();

    private String endMessage = "";

    private Throwable error = null;
    private boolean executeFinished = false;

    public void log(final String message) {
        logBuilder.append(message).append("\n");
    }

    public String getLog() {
        return logBuilder.toString();
    }

    public JobStatus getStatus() {
        if (future != null && status == JobStatus.PENDING) {
// Path: src/main/java/com/indeed/proctor/webapp/extensions/AfterBackgroundJobExecute.java
// public interface AfterBackgroundJobExecute {
//     <T> void afterExecute(final BackgroundJob<T> job, T result);
// }
// 
// Path: src/main/java/com/indeed/proctor/webapp/extensions/BeforeBackgroundJobExecute.java
// public interface BeforeBackgroundJobExecute {
//     <T> void beforeExecute(final BackgroundJob<T> job);
// }


// Path: src/main/java/com/indeed/proctor/webapp/jobs/BackgroundJob.java
import com.google.common.collect.Lists;
import com.indeed.proctor.webapp.extensions.AfterBackgroundJobExecute;
import com.indeed.proctor.webapp.extensions.BeforeBackgroundJobExecute;
import org.apache.log4j.Logger;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

package com.indeed.proctor.webapp.jobs;



/**
 */
public abstract class BackgroundJob<T> implements Callable<T> {
    private static final Logger LOGGER = Logger.getLogger(BackgroundJob.class);

    private Future<T> future;
    private JobStatus status = JobStatus.PENDING;
    protected final StringBuilder logBuilder = new StringBuilder();

    private Long id;
    private UUID uuid;

    private final long createdTime = System.currentTimeMillis();

    // URL to direct users to upon completion
    private final List<ResultUrl> urls = Lists.newArrayList();

    private String endMessage = "";

    private Throwable error = null;
    private boolean executeFinished = false;

    public void log(final String message) {
        logBuilder.append(message).append("\n");
    }

    public String getLog() {
        return logBuilder.toString();
    }

    public JobStatus getStatus() {
        if (future != null && status == JobStatus.PENDING) {
            if (future.isCancelled()) {