// Path: domain/src/main/java/me/panavtec/cleancontacts/domain/interactors/InteractorError.java
// public interface InteractorError {
// }
// 
// Path: domain/src/main/java/me/panavtec/cleancontacts/domain/interactors/InteractorResponse.java
// public class InteractorResponse<T> {
// 
//   private InteractorError error;
//   private T result;
// 
//   public InteractorResponse(InteractorError error) {
//     this.error = error;
//   }
// 
//   public InteractorResponse(T result) {
//     this.result = result;
//   }
// 
//   public InteractorError getError() {
//     return error;
//   }
// 
//   public T getResult() {
//     return result;
//   }
// 
//   public boolean hasError() {
//     return error != null;
//   }
// }
// 
// Path: presentation/src/main/java/me/panavtec/cleancontacts/presentation/InteractorResult.java
// public interface InteractorResult<T> {
//   void onResult(T result);
// }
// 
// Path: presentation/src/main/java/me/panavtec/cleancontacts/presentation/invoker/InteractorExecution.java
// public class InteractorExecution<T> {
//   private InteractorResult<T> interactorResult;
//   private final Map<Class<? extends InteractorError>, InteractorResult<? extends InteractorError>> errors =
//       new HashMap<>(0);
//   private final Interactor<InteractorResponse<T>> interactor;
//   private int priority;
// 
//   public InteractorExecution(Interactor<InteractorResponse<T>> interactor) {
//     this.interactor = interactor;
//   }
// 
//   public InteractorExecution<T> result(InteractorResult<T> interactorResult) {
//     this.interactorResult = interactorResult;
//     return this;
//   }
// 
//   public InteractorExecution<T> error(Class<? extends InteractorError> errorClass,
//       InteractorResult<? extends InteractorError> interactorError) {
//     this.errors.put(errorClass, interactorError);
//     return this;
//   }
// 
//   public InteractorExecution<T> priority(int priority) {
//     this.priority = priority;
//     return this;
//   }
// 
//   public Interactor<InteractorResponse<T>> getInteractor() {
//     return interactor;
//   }
// 
//   public InteractorResult<? extends InteractorError> getInteractorErrorResult(
//       Class<? extends InteractorError> errorClass) {
//     return errors.get(errorClass);
//   }
// 
//   public InteractorResult<T> getInteractorResult() {
//     return interactorResult;
//   }
// 
//   public void execute(InteractorInvoker interactorInvoker) {
//     interactorInvoker.execute(this);
//   }
// 
//   public int getPriority() {
//     return priority;
//   }
// }


import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import me.panavtec.cleancontacts.domain.interactors.InteractorError;
import me.panavtec.cleancontacts.domain.interactors.InteractorResponse;
import me.panavtec.cleancontacts.presentation.InteractorResult;
import me.panavtec.cleancontacts.presentation.invoker.InteractorExecution;
package me.panavtec.cleancontacts.domain.invoker;


public class InteractorExecutionFutureTask<T> extends FutureTask<T>
    implements PriorizableInteractor {

  private final InteractorExecution<T> interactorExecution;
  private final Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
  private final String description;

  public InteractorExecutionFutureTask(InteractorExecution<T> interactorExecution,
      Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
    super((Callable<T>) interactorExecution.getInteractor());
    this.interactorExecution = interactorExecution;
    this.uncaughtExceptionHandler = uncaughtExceptionHandler;
    this.description = interactorExecution.getInteractor().getClass().toString();
  }

  @Override protected void done() {
    super.done();
    try {
      handleResponse((InteractorResponse<T>) get());
    } catch (Exception e) {
      handleException(e);
    }
  }

  private void handleException(Exception e) {
    Throwable causeException = e.getCause();
    unhandledException(causeException != null ? causeException : e);
  }

// Path: domain/src/main/java/me/panavtec/cleancontacts/domain/interactors/InteractorError.java
// public interface InteractorError {
// }
// 
// Path: domain/src/main/java/me/panavtec/cleancontacts/domain/interactors/InteractorResponse.java
// public class InteractorResponse<T> {
// 
//   private InteractorError error;
//   private T result;
// 
//   public InteractorResponse(InteractorError error) {
//     this.error = error;
//   }
// 
//   public InteractorResponse(T result) {
//     this.result = result;
//   }
// 
//   public InteractorError getError() {
//     return error;
//   }
// 
//   public T getResult() {
//     return result;
//   }
// 
//   public boolean hasError() {
//     return error != null;
//   }
// }
// 
// Path: presentation/src/main/java/me/panavtec/cleancontacts/presentation/InteractorResult.java
// public interface InteractorResult<T> {
//   void onResult(T result);
// }
// 
// Path: presentation/src/main/java/me/panavtec/cleancontacts/presentation/invoker/InteractorExecution.java
// public class InteractorExecution<T> {
//   private InteractorResult<T> interactorResult;
//   private final Map<Class<? extends InteractorError>, InteractorResult<? extends InteractorError>> errors =
//       new HashMap<>(0);
//   private final Interactor<InteractorResponse<T>> interactor;
//   private int priority;
// 
//   public InteractorExecution(Interactor<InteractorResponse<T>> interactor) {
//     this.interactor = interactor;
//   }
// 
//   public InteractorExecution<T> result(InteractorResult<T> interactorResult) {
//     this.interactorResult = interactorResult;
//     return this;
//   }
// 
//   public InteractorExecution<T> error(Class<? extends InteractorError> errorClass,
//       InteractorResult<? extends InteractorError> interactorError) {
//     this.errors.put(errorClass, interactorError);
//     return this;
//   }
// 
//   public InteractorExecution<T> priority(int priority) {
//     this.priority = priority;
//     return this;
//   }
// 
//   public Interactor<InteractorResponse<T>> getInteractor() {
//     return interactor;
//   }
// 
//   public InteractorResult<? extends InteractorError> getInteractorErrorResult(
//       Class<? extends InteractorError> errorClass) {
//     return errors.get(errorClass);
//   }
// 
//   public InteractorResult<T> getInteractorResult() {
//     return interactorResult;
//   }
// 
//   public void execute(InteractorInvoker interactorInvoker) {
//     interactorInvoker.execute(this);
//   }
// 
//   public int getPriority() {
//     return priority;
//   }
// }


// Path: app/src/main/java/me/panavtec/cleancontacts/domain/invoker/InteractorExecutionFutureTask.java
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import me.panavtec.cleancontacts.domain.interactors.InteractorError;
import me.panavtec.cleancontacts.domain.interactors.InteractorResponse;
import me.panavtec.cleancontacts.presentation.InteractorResult;
import me.panavtec.cleancontacts.presentation.invoker.InteractorExecution;

package me.panavtec.cleancontacts.domain.invoker;


public class InteractorExecutionFutureTask<T> extends FutureTask<T>
    implements PriorizableInteractor {

  private final InteractorExecution<T> interactorExecution;
  private final Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
  private final String description;

  public InteractorExecutionFutureTask(InteractorExecution<T> interactorExecution,
      Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
    super((Callable<T>) interactorExecution.getInteractor());
    this.interactorExecution = interactorExecution;
    this.uncaughtExceptionHandler = uncaughtExceptionHandler;
    this.description = interactorExecution.getInteractor().getClass().toString();
  }

  @Override protected void done() {
    super.done();
    try {
      handleResponse((InteractorResponse<T>) get());
    } catch (Exception e) {
      handleException(e);
    }
  }

  private void handleException(Exception e) {
    Throwable causeException = e.getCause();
    unhandledException(causeException != null ? causeException : e);
  }

  private void handleResponse(InteractorResponse<T> response) {