// Path: library/src/main/java/fr/prcaen/externalresources/exception/ExternalResourceException.java
// public class ExternalResourceException extends RuntimeException {
// 
//   public ExternalResourceException(String detailMessage) {
//     super(detailMessage);
//   }
// 
//   public ExternalResourceException(String message, Throwable cause) {
//     super(message, cause);
//   }
// 
//   public ExternalResourceException(Throwable cause) {
//     super(cause);
//   }
// }
// 
// Path: library/src/main/java/fr/prcaen/externalresources/exception/ResponseException.java
// public final class ResponseException extends ExternalResourceException {
// 
//   private final boolean localCacheOnly;
//   private final int responseCode;
// 
//   public ResponseException(String message, @Cache.Policy int networkPolicy, int responseCode) {
//     super(message);
// 
//     this.localCacheOnly = networkPolicy == Cache.POLICY_OFFLINE;
//     this.responseCode = responseCode;
//   }
// 
//   public boolean isLocalCacheOnly() {
//     return localCacheOnly;
//   }
// 
//   public int getResponseCode() {
//     return responseCode;
//   }
// }
// 
// Path: library/src/main/java/fr/prcaen/externalresources/model/Resources.java
// @SuppressWarnings("unused") public final class Resources {
//   protected final ConcurrentHashMap<String, Resource> members;
// 
//   public Resources() {
//     this.members = new ConcurrentHashMap<>();
//   }
// 
//   public Resources(@NonNull ConcurrentHashMap<String, Resource> members) {
//     this.members = members;
//   }
// 
//   public static Resources from(Reader reader, Converter converter) throws IOException {
//     return converter.fromReader(reader);
//   }
// 
//   public static Resources from(String string, Converter converter) throws IOException {
//     return from(new StringReader(string), converter);
//   }
// 
//   public static Resources fromJson(Reader reader) throws IOException {
//     return from(reader, new JsonConverter());
//   }
// 
//   public static Resources fromJson(String string) throws IOException {
//     return from(string, new JsonConverter());
//   }
// 
//   public static Resources fromJson(InputStream reader) throws IOException {
//     return fromJson(new InputStreamReader(reader));
//   }
// 
//   public static Resources fromXml(Reader reader) throws IOException {
//     return from(reader, new XmlConverter());
//   }
// 
//   public static Resources fromXml(String string) throws IOException {
//     return from(string, new XmlConverter());
//   }
// 
//   public static Resources fromXml(InputStream reader) throws IOException {
//     return fromXml(new InputStreamReader(reader));
//   }
// 
//   public Resource add(String key, Resource value) {
//     return members.put(key, value);
//   }
// 
//   @NonNull protected Set<Entry<String, Resource>> entrySet() {
//     return members.entrySet();
//   }
// 
//   public boolean has(String key) {
//     return members.containsKey(key);
//   }
// 
//   public Resource get(String key) {
//     return members.get(key);
//   }
// 
//   public Resources merge(Resources resources) {
//     members.putAll(resources.members);
// 
//     return this;
//   }
// }


import android.support.annotation.NonNull;
import fr.prcaen.externalresources.exception.ExternalResourceException;
import fr.prcaen.externalresources.exception.ResponseException;
import fr.prcaen.externalresources.model.Resources;
package fr.prcaen.externalresources;


public final class ResourcesRunnable implements Runnable {

  public static final int RETRY_COUNT = 2;
  private static final String THREAD_NAME_SUFFIX = "-external-resources";

  private final Downloader downloader;
  private final Dispatcher dispatcher;
  @Cache.Policy private final int cachePolicy;
  private int retryCount;

  public ResourcesRunnable(@NonNull Downloader downloader, @NonNull Dispatcher dispatcher,
      @Cache.Policy int policy) {
    this.downloader = downloader;
    this.dispatcher = dispatcher;
    this.cachePolicy = policy;
    this.retryCount = RETRY_COUNT;
  }

  @Override public void run() {
    Thread.currentThread().setName(Thread.currentThread().getId() + THREAD_NAME_SUFFIX);

    try {
      Resources resources = downloader.load(cachePolicy);
      if (null != resources) {
        dispatcher.dispatchDone(resources);
      } else {
// Path: library/src/main/java/fr/prcaen/externalresources/exception/ExternalResourceException.java
// public class ExternalResourceException extends RuntimeException {
// 
//   public ExternalResourceException(String detailMessage) {
//     super(detailMessage);
//   }
// 
//   public ExternalResourceException(String message, Throwable cause) {
//     super(message, cause);
//   }
// 
//   public ExternalResourceException(Throwable cause) {
//     super(cause);
//   }
// }
// 
// Path: library/src/main/java/fr/prcaen/externalresources/exception/ResponseException.java
// public final class ResponseException extends ExternalResourceException {
// 
//   private final boolean localCacheOnly;
//   private final int responseCode;
// 
//   public ResponseException(String message, @Cache.Policy int networkPolicy, int responseCode) {
//     super(message);
// 
//     this.localCacheOnly = networkPolicy == Cache.POLICY_OFFLINE;
//     this.responseCode = responseCode;
//   }
// 
//   public boolean isLocalCacheOnly() {
//     return localCacheOnly;
//   }
// 
//   public int getResponseCode() {
//     return responseCode;
//   }
// }
// 
// Path: library/src/main/java/fr/prcaen/externalresources/model/Resources.java
// @SuppressWarnings("unused") public final class Resources {
//   protected final ConcurrentHashMap<String, Resource> members;
// 
//   public Resources() {
//     this.members = new ConcurrentHashMap<>();
//   }
// 
//   public Resources(@NonNull ConcurrentHashMap<String, Resource> members) {
//     this.members = members;
//   }
// 
//   public static Resources from(Reader reader, Converter converter) throws IOException {
//     return converter.fromReader(reader);
//   }
// 
//   public static Resources from(String string, Converter converter) throws IOException {
//     return from(new StringReader(string), converter);
//   }
// 
//   public static Resources fromJson(Reader reader) throws IOException {
//     return from(reader, new JsonConverter());
//   }
// 
//   public static Resources fromJson(String string) throws IOException {
//     return from(string, new JsonConverter());
//   }
// 
//   public static Resources fromJson(InputStream reader) throws IOException {
//     return fromJson(new InputStreamReader(reader));
//   }
// 
//   public static Resources fromXml(Reader reader) throws IOException {
//     return from(reader, new XmlConverter());
//   }
// 
//   public static Resources fromXml(String string) throws IOException {
//     return from(string, new XmlConverter());
//   }
// 
//   public static Resources fromXml(InputStream reader) throws IOException {
//     return fromXml(new InputStreamReader(reader));
//   }
// 
//   public Resource add(String key, Resource value) {
//     return members.put(key, value);
//   }
// 
//   @NonNull protected Set<Entry<String, Resource>> entrySet() {
//     return members.entrySet();
//   }
// 
//   public boolean has(String key) {
//     return members.containsKey(key);
//   }
// 
//   public Resource get(String key) {
//     return members.get(key);
//   }
// 
//   public Resources merge(Resources resources) {
//     members.putAll(resources.members);
// 
//     return this;
//   }
// }


// Path: library/src/main/java/fr/prcaen/externalresources/ResourcesRunnable.java
import android.support.annotation.NonNull;
import fr.prcaen.externalresources.exception.ExternalResourceException;
import fr.prcaen.externalresources.exception.ResponseException;
import fr.prcaen.externalresources.model.Resources;

package fr.prcaen.externalresources;


public final class ResourcesRunnable implements Runnable {

  public static final int RETRY_COUNT = 2;
  private static final String THREAD_NAME_SUFFIX = "-external-resources";

  private final Downloader downloader;
  private final Dispatcher dispatcher;
  @Cache.Policy private final int cachePolicy;
  private int retryCount;

  public ResourcesRunnable(@NonNull Downloader downloader, @NonNull Dispatcher dispatcher,
      @Cache.Policy int policy) {
    this.downloader = downloader;
    this.dispatcher = dispatcher;
    this.cachePolicy = policy;
    this.retryCount = RETRY_COUNT;
  }

  @Override public void run() {
    Thread.currentThread().setName(Thread.currentThread().getId() + THREAD_NAME_SUFFIX);

    try {
      Resources resources = downloader.load(cachePolicy);
      if (null != resources) {
        dispatcher.dispatchDone(resources);
      } else {
        dispatcher.dispatchFailed(new ExternalResourceException("Resources are null."));