// Path: src/main/java/javapns/devices/Device.java
// public interface Device {
//   /**
//    * An id representing a particular device.
//    * <p>
//    * Note that this is a local reference to the device,
//    * which is not related to the actual device UUID or
//    * other device-specific identification. Most of the
//    * time, this deviceId should be the same as the token.
//    *
//    * @return the device id
//    */
//   String getDeviceId();
// 
//   /**
//    * An id representing a particular device.
//    * <p>
//    * Note that this is a local reference to the device,
//    * which is not related to the actual device UUID or
//    * other device-specific identification. Most of the
//    * time, this deviceId should be the same as the token.
//    *
//    * @param id the device id
//    */
//   void setDeviceId(String id);
// 
//   /**
//    * A device token.
//    *
//    * @return the device token
//    */
//   String getToken();
// 
//   /**
//    * Set the device token
//    *
//    * @param token
//    */
//   void setToken(String token);
// 
//   /**
//    * @return the last register
//    */
//   Timestamp getLastRegister();
// 
//   /**
//    * @param lastRegister the last register
//    */
//   void setLastRegister(Timestamp lastRegister);
// }
// 
// Path: src/main/java/javapns/devices/Devices.java
// public class Devices {
// 
//   private Devices() {}
// 
//   public static List<Device> asDevices(final Object rawList) {
//     final List<Device> list = new ArrayList<>();
//     if (rawList == null) {
//       return list;
//     }
// 
//     if (rawList instanceof List) {
//       final List devices = (List) rawList;
//       if (devices.isEmpty()) {
//         return list;
//       }
// 
//       final Object firstDevice = devices.get(0);
//       if (firstDevice instanceof Device) {
//         //noinspection unchecked
//         return devices;
//       } else if (firstDevice instanceof String) {
//         for (final Object token : devices) {
//           final BasicDevice device = new BasicDevice();
//           device.setToken((String) token);
//           list.add(device);
//         }
//       }
//     } else if (rawList instanceof String[]) {
//       final String[] tokens = (String[]) rawList;
//       for (final String token : tokens) {
//         final BasicDevice device = new BasicDevice();
//         device.setToken(token);
//         list.add(device);
//       }
//     } else if (rawList instanceof Device[]) {
//       final Device[] dvs = (Device[]) rawList;
//       return Arrays.asList(dvs);
//     } else if (rawList instanceof String) {
//       final BasicDevice device = new BasicDevice();
//       device.setToken((String) rawList);
//       list.add(device);
//     } else if (rawList instanceof Device) {
//       list.add((Device) rawList);
//     } else {
//       throw new IllegalArgumentException("Device list type not supported. Supported types are: String[], List<String>, Device[], List<Device>, String and Device");
//     }
//     return list;
//   }
// 
//   public static List<PayloadPerDevice> asPayloadsPerDevices(final Object rawList) {
//     final List<PayloadPerDevice> list = new ArrayList<>();
//     if (rawList == null) {
//       return list;
//     }
//     if (rawList instanceof List) {
//       final List devices = (List) rawList;
//       if (devices.isEmpty()) {
//         return list;
//       }
//       //noinspection unchecked
//       return devices;
//     } else if (rawList instanceof PayloadPerDevice[]) {
//       final PayloadPerDevice[] dvs = (PayloadPerDevice[]) rawList;
//       return Arrays.asList(dvs);
//     } else if (rawList instanceof PayloadPerDevice) {
//       list.add((PayloadPerDevice) rawList);
//     } else {
//       throw new IllegalArgumentException("PayloadPerDevice list type not supported. Supported types are: PayloadPerDevice[], List<PayloadPerDevice> and PayloadPerDevice");
//     }
//     return list;
//   }
// }
// 
// Path: src/main/java/javapns/devices/exceptions/InvalidDeviceTokenFormatException.java
// public class InvalidDeviceTokenFormatException extends Exception {
// 
//   private static final long serialVersionUID = -8571997399252125457L;
// 
//   public InvalidDeviceTokenFormatException(final String message) {
//     super(message);
//   }
// 
//   public InvalidDeviceTokenFormatException(final String token, final String problem) {
//     super(String.format("Device token cannot be parsed, most likely because it contains invalid hexadecimal characters: %s in %s", problem, token));
//   }
// 
// }


import javapns.devices.Device;
import javapns.devices.Devices;
import javapns.devices.exceptions.InvalidDeviceTokenFormatException;
import javapns.notification.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.stream.Collectors;
   *
   * @return a list of critical exceptions
   */
  public List<Exception> getCriticalExceptions() {
    final List<Exception> exceptions = new ArrayList<>();
    for (final NotificationThread thread : threads) {
      final Exception exception = thread.getCriticalException();
      if (exception != null) {
        exceptions.add(exception);
      }
    }
    return exceptions;
  }

  /**
   * Get the amount of time that the library will wait after starting a thread and before starting the next one.
   *
   * @return the number of milliseconds currently configured
   */
  public long getDelayBetweenThreads() {
    return delayBetweenThreads;
  }

  /**
   * Set the amount of time that the library will wait after starting a thread and before starting the next one.
   * The default delay is 200 milliseconds.  This means that starting 10 threads will take 2 seconds to fully start.
   * As discussed in issue report #102, adding a delay improves reliability.
   *
   * @param delayBetweenThreads a number of milliseconds
   */
// Path: src/main/java/javapns/devices/Device.java
// public interface Device {
//   /**
//    * An id representing a particular device.
//    * <p>
//    * Note that this is a local reference to the device,
//    * which is not related to the actual device UUID or
//    * other device-specific identification. Most of the
//    * time, this deviceId should be the same as the token.
//    *
//    * @return the device id
//    */
//   String getDeviceId();
// 
//   /**
//    * An id representing a particular device.
//    * <p>
//    * Note that this is a local reference to the device,
//    * which is not related to the actual device UUID or
//    * other device-specific identification. Most of the
//    * time, this deviceId should be the same as the token.
//    *
//    * @param id the device id
//    */
//   void setDeviceId(String id);
// 
//   /**
//    * A device token.
//    *
//    * @return the device token
//    */
//   String getToken();
// 
//   /**
//    * Set the device token
//    *
//    * @param token
//    */
//   void setToken(String token);
// 
//   /**
//    * @return the last register
//    */
//   Timestamp getLastRegister();
// 
//   /**
//    * @param lastRegister the last register
//    */
//   void setLastRegister(Timestamp lastRegister);
// }
// 
// Path: src/main/java/javapns/devices/Devices.java
// public class Devices {
// 
//   private Devices() {}
// 
//   public static List<Device> asDevices(final Object rawList) {
//     final List<Device> list = new ArrayList<>();
//     if (rawList == null) {
//       return list;
//     }
// 
//     if (rawList instanceof List) {
//       final List devices = (List) rawList;
//       if (devices.isEmpty()) {
//         return list;
//       }
// 
//       final Object firstDevice = devices.get(0);
//       if (firstDevice instanceof Device) {
//         //noinspection unchecked
//         return devices;
//       } else if (firstDevice instanceof String) {
//         for (final Object token : devices) {
//           final BasicDevice device = new BasicDevice();
//           device.setToken((String) token);
//           list.add(device);
//         }
//       }
//     } else if (rawList instanceof String[]) {
//       final String[] tokens = (String[]) rawList;
//       for (final String token : tokens) {
//         final BasicDevice device = new BasicDevice();
//         device.setToken(token);
//         list.add(device);
//       }
//     } else if (rawList instanceof Device[]) {
//       final Device[] dvs = (Device[]) rawList;
//       return Arrays.asList(dvs);
//     } else if (rawList instanceof String) {
//       final BasicDevice device = new BasicDevice();
//       device.setToken((String) rawList);
//       list.add(device);
//     } else if (rawList instanceof Device) {
//       list.add((Device) rawList);
//     } else {
//       throw new IllegalArgumentException("Device list type not supported. Supported types are: String[], List<String>, Device[], List<Device>, String and Device");
//     }
//     return list;
//   }
// 
//   public static List<PayloadPerDevice> asPayloadsPerDevices(final Object rawList) {
//     final List<PayloadPerDevice> list = new ArrayList<>();
//     if (rawList == null) {
//       return list;
//     }
//     if (rawList instanceof List) {
//       final List devices = (List) rawList;
//       if (devices.isEmpty()) {
//         return list;
//       }
//       //noinspection unchecked
//       return devices;
//     } else if (rawList instanceof PayloadPerDevice[]) {
//       final PayloadPerDevice[] dvs = (PayloadPerDevice[]) rawList;
//       return Arrays.asList(dvs);
//     } else if (rawList instanceof PayloadPerDevice) {
//       list.add((PayloadPerDevice) rawList);
//     } else {
//       throw new IllegalArgumentException("PayloadPerDevice list type not supported. Supported types are: PayloadPerDevice[], List<PayloadPerDevice> and PayloadPerDevice");
//     }
//     return list;
//   }
// }
// 
// Path: src/main/java/javapns/devices/exceptions/InvalidDeviceTokenFormatException.java
// public class InvalidDeviceTokenFormatException extends Exception {
// 
//   private static final long serialVersionUID = -8571997399252125457L;
// 
//   public InvalidDeviceTokenFormatException(final String message) {
//     super(message);
//   }
// 
//   public InvalidDeviceTokenFormatException(final String token, final String problem) {
//     super(String.format("Device token cannot be parsed, most likely because it contains invalid hexadecimal characters: %s in %s", problem, token));
//   }
// 
// }


// Path: src/main/java/javapns/notification/transmission/NotificationThreads.java
import javapns.devices.Device;
import javapns.devices.Devices;
import javapns.devices.exceptions.InvalidDeviceTokenFormatException;
import javapns.notification.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.stream.Collectors;

   *
   * @return a list of critical exceptions
   */
  public List<Exception> getCriticalExceptions() {
    final List<Exception> exceptions = new ArrayList<>();
    for (final NotificationThread thread : threads) {
      final Exception exception = thread.getCriticalException();
      if (exception != null) {
        exceptions.add(exception);
      }
    }
    return exceptions;
  }

  /**
   * Get the amount of time that the library will wait after starting a thread and before starting the next one.
   *
   * @return the number of milliseconds currently configured
   */
  public long getDelayBetweenThreads() {
    return delayBetweenThreads;
  }

  /**
   * Set the amount of time that the library will wait after starting a thread and before starting the next one.
   * The default delay is 200 milliseconds.  This means that starting 10 threads will take 2 seconds to fully start.
   * As discussed in issue report #102, adding a delay improves reliability.
   *
   * @param delayBetweenThreads a number of milliseconds
   */
  public void setDelayBetweenThreads(final long delayBetweenThreads) {