/**
   * Processes the given transaction, updates its state and returns the same transaction instance or
   * a new one (an instance of a <code>Transaction</code> subclass), which is based on the old
   * transaction, but adds more (adapter specific) information to it.
   *
   * <p>The current implementation fails any transaction with the <code>Transaction.ASSIGNED</code>
   * state, so it has to be overriden to work properly. It also sets the transaction processor of
   * the given transaction to the payment module instance. It's recomended to call this method from
   * the overriden one for every unhandled transaction (with the state, which can't be further
   * processed in the adapter). It ensures that the control over the transaction will return to the
   * payment module.
   *
   * @param transaction the transaction to be processed
   * @return the transaction after processing
   */
  public Transaction process(Transaction transaction) {
    if (transaction.getState() == Transaction.ASSIGNED) {
      // was not processed by the child adapter class
      transaction.setState(Transaction.FAILED);
      transaction.setNeedsUI(false);
    }

    // return any transaction which was not processed by the payment
    // adapter back to the payment module
    transaction.setTransactionProcessor(PaymentModule.getInstance());
    return transaction;
  }
  /**
   * Returns a question which is used for this adapter instance when the user chooses between
   * providers for the particular payment.
   *
   * @param provider the application supplied provider name
   * @param price the price to pay when using the provider
   * @param currency the currency of the payment
   * @return the question to ask (Are you sure, you want to buy this feature...)
   */
  public String getPaymentQuestion(String provider, double price, String currency) {
    int multiplied = (int) (price * 100 + 0.5);
    String priceString = Integer.toString(multiplied);
    int length = priceString.length();

    String[] values = {
      currency,
      priceString.substring(0, length - 2),
      priceString.substring(length - 2),
      getDisplayName(),
      provider
    };

    return PaymentModule.getInstance()
        .getUtilities()
        .getString(Utils.PAYMENT_UPDATE_DLG_QUESTION, values);
  }
 /**
  * Replaces the current <code>Displayable</code> with the new one if the <code>nextDisplayable
  * </code> is not <code>null</code> or it recovers the previous <code>Displayable</code> if the
  * <code>nextDisplayable</code> is <code>null</code>.
  *
  * @param token a security token, which allows preempting
  * @param nextDisplayable the <code>Displayable</code> to show or <code>null</code> if the
  *     recovery of the old <code>Displayable</code> is requested
  */
 protected final void preemptDisplay(SecurityToken token, Displayable nextDisplayable) {
   PaymentModule.getInstance().preemptDisplay(token, nextDisplayable);
 }