@SuppressWarnings("boxing")
  @Override
  public <T> Subscription<T> open(
      Class<T> clazz, final long id, final SubscriptionConnectionOptions options, String database)
      throws SubscriptionException {
    if (options == null) {
      throw new IllegalArgumentException("Cannot open a subscription if options are null");
    }

    if (options.getBatchOptions() == null) {
      throw new IllegalArgumentException("Cannot open a subscription if batch options are null");
    }

    if (options.getBatchOptions().getMaxSize() != null
        && options.getBatchOptions().getMaxSize() < 16 * 1024) {
      throw new IllegalArgumentException(
          "Max size value of batch options cannot be lower than that 16 KB");
    }

    final IDatabaseCommands commands =
        database == null
            ? documentStore.getDatabaseCommands()
            : documentStore.getDatabaseCommands().forDatabase(database);

    boolean open = true;
    try {

      sendOpenSubscriptionRequest(commands, id, options);
    } catch (SubscriptionException subscriptionException) {
      if (options.getStrategy() != SubscriptionOpeningStrategy.WAIT_FOR_FREE
          || !(subscriptionException instanceof SubscriptionInUseException)) {
        throw subscriptionException;
      }
      open = false;
    }

    Subscription<T> subscription =
        new Subscription<>(
            clazz,
            id,
            Lang.coalesce(database, MultiDatabase.getDatabaseName(documentStore.getUrl())),
            options,
            commands,
            documentStore.changes(database),
            documentStore.getConventions(),
            open,
            new Action0() {
              @SuppressWarnings("synthetic-access")
              @Override
              public void apply() {
                sendOpenSubscriptionRequest(
                    commands, id,
                    options); // to ensure that subscription is open try to call it with the same
                              // connection id
              }
            });

    subscriptions.add(subscription);
    return subscription;
  }